From fe607f640c9fb6aa00aa5a01eabf602e5480ed0f Mon Sep 17 00:00:00 2001 From: Erik Tiekstra Date: Thu, 26 Sep 2024 15:20:22 +0200 Subject: [PATCH] feat(SW-325): added additional poi groups --- .../HotelPage/Map/DynamicMap/Map/index.tsx | 3 +- .../Map/DynamicMap/Sidebar/index.tsx | 18 ++++---- .../HotelPage/Map/MapCard/index.tsx | 7 ++- components/Icons/Airplane.tsx | 40 +++++++++++++++++ components/Icons/Business.tsx | 40 +++++++++++++++++ components/Icons/Camera.tsx | 27 ++++++++--- components/Icons/get-icon-by-icon-name.ts | 6 +++ components/Icons/index.tsx | 2 + components/Maps/Markers/Poi/index.tsx | 9 ++-- components/Maps/Markers/Poi/poi.module.css | 45 ++++++------------- components/Maps/Markers/Poi/variants.ts | 27 ++++------- components/Maps/Markers/utils.ts | 39 +++++++++------- server/routers/hotels/output.ts | 33 +++++--------- server/routers/hotels/utils.ts | 42 +++++++++++------ types/components/icon.ts | 2 + types/components/maps/poiMarker.ts | 7 +++ types/hotel.ts | 30 ++++++++++++- 17 files changed, 254 insertions(+), 123 deletions(-) create mode 100644 components/Icons/Airplane.tsx create mode 100644 components/Icons/Business.tsx diff --git a/components/ContentType/HotelPage/Map/DynamicMap/Map/index.tsx b/components/ContentType/HotelPage/Map/DynamicMap/Map/index.tsx index a049e90c4..60a30a9a3 100644 --- a/components/ContentType/HotelPage/Map/DynamicMap/Map/index.tsx +++ b/components/ContentType/HotelPage/Map/DynamicMap/Map/index.tsx @@ -80,7 +80,8 @@ export default function MapContent({ className={`${styles.poi} ${activePoi === poi.name ? styles.active : ""}`} > diff --git a/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx b/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx index 217fa51bd..c76b3f089 100644 --- a/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx +++ b/components/ContentType/HotelPage/Map/DynamicMap/Sidebar/index.tsx @@ -20,12 +20,10 @@ export default function Sidebar({ }: SidebarProps) { const intl = useIntl() const [isFullScreenSidebar, setIsFullScreenSidebar] = useState(false) - const poiCategories = new Set( - pointsOfInterest.map(({ category }) => category) - ) - const poisInCategories = Array.from(poiCategories).map((category) => ({ - category, - pois: pointsOfInterest.filter((poi) => poi.category === category), + const poiGroups = new Set(pointsOfInterest.map(({ group }) => group)) + const poisInGroups = Array.from(poiGroups).map((group) => ({ + group, + pois: pointsOfInterest.filter((poi) => poi.group === group), })) function toggleFullScreenSidebar() { @@ -60,9 +58,9 @@ export default function Sidebar({ )} - {poisInCategories.map(({ category, pois }) => + {poisInGroups.map(({ group, pois }) => pois.length ? ( -
+

- - {intl.formatMessage({ id: category })} + + {intl.formatMessage({ id: group })}

    diff --git a/components/ContentType/HotelPage/Map/MapCard/index.tsx b/components/ContentType/HotelPage/Map/MapCard/index.tsx index 8764870bc..79e9759be 100644 --- a/components/ContentType/HotelPage/Map/MapCard/index.tsx +++ b/components/ContentType/HotelPage/Map/MapCard/index.tsx @@ -39,7 +39,12 @@ export default function MapCard({ hotelName, pois }: MapCardProps) {
      {pois.map((poi) => (
    • - + {poi.name} {poi.distance} km
    • diff --git a/components/Icons/Airplane.tsx b/components/Icons/Airplane.tsx new file mode 100644 index 000000000..c68c37ce1 --- /dev/null +++ b/components/Icons/Airplane.tsx @@ -0,0 +1,40 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function AirplaneIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Business.tsx b/components/Icons/Business.tsx new file mode 100644 index 000000000..cb6ded53d --- /dev/null +++ b/components/Icons/Business.tsx @@ -0,0 +1,40 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function BusinessIcon({ + className, + color, + ...props +}: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/Camera.tsx b/components/Icons/Camera.tsx index bed8a79e6..728a9e1c1 100644 --- a/components/Icons/Camera.tsx +++ b/components/Icons/Camera.tsx @@ -8,16 +8,29 @@ export default function CameraIcon({ className, color, ...props }: IconProps) { - + + + + + + ) } diff --git a/components/Icons/get-icon-by-icon-name.ts b/components/Icons/get-icon-by-icon-name.ts index 20bf8d9a8..3a443cea2 100644 --- a/components/Icons/get-icon-by-icon-name.ts +++ b/components/Icons/get-icon-by-icon-name.ts @@ -6,9 +6,11 @@ import TripAdvisorIcon from "./TripAdvisor" import { AccessibilityIcon, AccountCircleIcon, + AirplaneIcon, ArrowRightIcon, BarIcon, BikingIcon, + BusinessIcon, CalendarIcon, CameraIcon, CellphoneIcon, @@ -66,12 +68,16 @@ export function getIconByIconName(icon?: IconName): FC | null { return AccessibilityIcon case IconName.AccountCircle: return AccountCircleIcon + case IconName.Airplane: + return AirplaneIcon case IconName.ArrowRight: return ArrowRightIcon case IconName.Bar: return BarIcon case IconName.Biking: return BikingIcon + case IconName.Business: + return BusinessIcon case IconName.Calendar: return CalendarIcon case IconName.Camera: diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index 9d7c0bd2c..db5e29bbb 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -1,8 +1,10 @@ export { default as AccessibilityIcon } from "./Accessibility" export { default as AccountCircleIcon } from "./AccountCircle" +export { default as AirplaneIcon } from "./Airplane" export { default as ArrowRightIcon } from "./ArrowRight" export { default as BarIcon } from "./Bar" export { default as BikingIcon } from "./Biking" +export { default as BusinessIcon } from "./Business" export { default as CalendarIcon } from "./Calendar" export { default as CameraIcon } from "./Camera" export { default as CellphoneIcon } from "./Cellphone" diff --git a/components/Maps/Markers/Poi/index.tsx b/components/Maps/Markers/Poi/index.tsx index db67af80b..9fa3d9e47 100644 --- a/components/Maps/Markers/Poi/index.tsx +++ b/components/Maps/Markers/Poi/index.tsx @@ -1,19 +1,20 @@ import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name" -import { getCategoryIconName } from "../utils" +import { getIconByPoiGroupAndCategory } from "../utils" import { poiVariants } from "./variants" import type { PoiMarkerProps } from "@/types/components/maps/poiMarker" export default function PoiMarker({ - category, + group, + categoryName, skipBackground, size = 16, className = "", }: PoiMarkerProps) { - const iconName = getCategoryIconName(category) + const iconName = getIconByPoiGroupAndCategory(group, categoryName) const Icon = iconName ? getIconByIconName(iconName) : null - const classNames = poiVariants({ category, skipBackground, className }) + const classNames = poiVariants({ group, skipBackground, className }) return Icon ? ( diff --git a/components/Maps/Markers/Poi/poi.module.css b/components/Maps/Markers/Poi/poi.module.css index e89b8f702..0a08151ef 100644 --- a/components/Maps/Markers/Poi/poi.module.css +++ b/components/Maps/Markers/Poi/poi.module.css @@ -7,46 +7,29 @@ This will be handled later. */ align-items: center; padding: var(--Spacing-x-half); border-radius: var(--Corner-radius-Rounded); - background-color: var(--Scandic-Beige-90); -} -.airport, -.amusementPark, -.busTerminal, -.fair, -.hospital, -.hotel, -.marketingCity { + background-color: var(--UI-Text-Placeholder); } -.museum { - background: var(--Base-Interactive-Surface-Secondary-normal); +.attractions { + background-color: var(--Base-Interactive-Surface-Secondary-normal); } -.nearbyCompanies, -.parkingGarage { +.business { + background-color: var(--Scandic-Yellow-50); } - -.restaurant { - background: var(--Scandic-Peach-50); +.location { + background-color: var(--UI-Text-Placeholder); } - -.shopping { - background: var(--Base-Interactive-Surface-Primary-normal); +.parking { + background-color: var(--UI-Text-Active); } -.sports, -.theatre { +.publicTransport { + background-color: var(--Base-Interactive-Surface-Tertiary-normal); } - -.tourist { - background: var(--Scandic-Yellow-60); -} - -.transportations { - background: var(--Base-Interactive-Surface-Tertiary-normal); -} -.zoo { +.shoppingDining { + background-color: var(--Base-Interactive-Surface-Primary-normal); } .icon.transparent { - background: transparent; + background-color: transparent; padding: 0; } diff --git a/components/Maps/Markers/Poi/variants.ts b/components/Maps/Markers/Poi/variants.ts index 6eed0ae58..873b4e219 100644 --- a/components/Maps/Markers/Poi/variants.ts +++ b/components/Maps/Markers/Poi/variants.ts @@ -2,26 +2,17 @@ import { cva } from "class-variance-authority" import styles from "./poi.module.css" +import { PointOfInterestGroupEnum } from "@/types/hotel" + export const poiVariants = cva(styles.icon, { variants: { - category: { - Airport: styles.airport, - "Amusement park": styles.amusementPark, - "Bus terminal": styles.busTerminal, - Fair: styles.fair, - Hospital: styles.hospital, - Hotel: styles.hotel, - "Marketing city": styles.marketingCity, - Museum: styles.museum, - "Nearby companies": styles.nearbyCompanies, - "Parking / Garage": styles.parkingGarage, - Restaurant: styles.restaurant, - Shopping: styles.shopping, - Sports: styles.sports, - Theatre: styles.theatre, - Tourist: styles.tourist, - Transportations: styles.transportations, - Zoo: styles.zoo, + group: { + [PointOfInterestGroupEnum.ATTRACTIONS]: styles.attractions, + [PointOfInterestGroupEnum.BUSINESS]: styles.business, + [PointOfInterestGroupEnum.LOCATION]: styles.location, + [PointOfInterestGroupEnum.PARKING]: styles.parking, + [PointOfInterestGroupEnum.PUBLIC_TRANSPORT]: styles.publicTransport, + [PointOfInterestGroupEnum.SHOPPING_DINING]: styles.shoppingDining, }, skipBackground: { true: styles.transparent, diff --git a/components/Maps/Markers/utils.ts b/components/Maps/Markers/utils.ts index bf3e5ec38..fd574eb87 100644 --- a/components/Maps/Markers/utils.ts +++ b/components/Maps/Markers/utils.ts @@ -1,21 +1,30 @@ import { IconName } from "@/types/components/icon" -import type { PointOfInterestCategory } from "@/types/hotel" +import { + PointOfInterestCategoryNameEnum, + PointOfInterestGroupEnum, +} from "@/types/hotel" -/* 2024-09-18: At the moment, the icons for the different categories is unknown. -This will be handled later. */ -export function getCategoryIconName(category?: PointOfInterestCategory | null) { - switch (category) { - case "Transportations": - return IconName.Train - case "Shopping": +export function getIconByPoiGroupAndCategory( + group: PointOfInterestGroupEnum, + category?: PointOfInterestCategoryNameEnum +) { + switch (group) { + case PointOfInterestGroupEnum.PUBLIC_TRANSPORT: + return category === PointOfInterestCategoryNameEnum.AIRPORT + ? IconName.Airplane + : IconName.Train + case PointOfInterestGroupEnum.ATTRACTIONS: + return category === PointOfInterestCategoryNameEnum.MUSEUM + ? IconName.Museum + : IconName.Camera + case PointOfInterestGroupEnum.BUSINESS: + return IconName.Business + case PointOfInterestGroupEnum.PARKING: + return IconName.Parking + case PointOfInterestGroupEnum.SHOPPING_DINING: return IconName.Shopping - case "Museum": - return IconName.Museum - case "Tourist": - return IconName.Cultural - case "Restaurant": - return IconName.Restaurant + case PointOfInterestGroupEnum.LOCATION: default: - return IconName.StarFilled + return IconName.Location } } diff --git a/server/routers/hotels/output.ts b/server/routers/hotels/output.ts index 82a51754b..7f57ba6cd 100644 --- a/server/routers/hotels/output.ts +++ b/server/routers/hotels/output.ts @@ -2,6 +2,13 @@ import { z } from "zod" import { toLang } from "@/server/utils" +import { getPoiGroupByCategoryName } from "./utils" + +import { + PointOfInterestCategoryNameEnum, + PointOfInterestGroupEnum, +} from "@/types/hotel" + const ratingsSchema = z .object({ tripAdvisor: z.object({ @@ -213,32 +220,15 @@ const rewardNightSchema = z.object({ }), }) -const poiCategories = z.enum([ - "Airport", - "Amusement park", - "Bus terminal", - "Fair", - "Hospital", - "Hotel", - "Marketing city", - "Museum", - "Nearby companies", - "Parking / Garage", - "Restaurant", - "Shopping", - "Sports", - "Theatre", - "Tourist", - "Transportations", - "Zoo", -]) +const poiGroups = z.nativeEnum(PointOfInterestGroupEnum) +const poiCategoryNames = z.nativeEnum(PointOfInterestCategoryNameEnum) export const pointOfInterestSchema = z .object({ name: z.string(), distance: z.number(), category: z.object({ - name: poiCategories, + name: poiCategoryNames, group: z.string(), }), location: locationSchema, @@ -247,7 +237,8 @@ export const pointOfInterestSchema = z .transform((poi) => ({ name: poi.name, distance: poi.distance, - category: poi.category.name, + categoryName: poi.category.name, + group: getPoiGroupByCategoryName(poi.category.name), coordinates: { lat: poi.location.latitude, lng: poi.location.longitude, diff --git a/server/routers/hotels/utils.ts b/server/routers/hotels/utils.ts index 6fa8e168f..d19d1a492 100644 --- a/server/routers/hotels/utils.ts +++ b/server/routers/hotels/utils.ts @@ -1,5 +1,3 @@ -import { IconName } from "@/types/components/icon" - import deepmerge from "deepmerge" import { unstable_cache } from "next/cache" @@ -15,23 +13,39 @@ import { } from "./output" import type { RequestOptionsWithOutBody } from "@/types/fetch" +import { + PointOfInterestCategoryNameEnum, + PointOfInterestGroupEnum, +} from "@/types/hotel" import type { Lang } from "@/constants/languages" import type { Endpoint } from "@/lib/api/endpoints" -export function getIconByPoiCategory(category: string) { +export function getPoiGroupByCategoryName( + category: PointOfInterestCategoryNameEnum +) { switch (category) { - case "Transportations": - return IconName.Train - case "Shopping": - return IconName.Shopping - case "Museum": - return IconName.Museum - case "Tourist": - return IconName.Cultural - case "Restaurant": - return IconName.Restaurant + case PointOfInterestCategoryNameEnum.AIRPORT: + case PointOfInterestCategoryNameEnum.BUS_TERMINAL: + case PointOfInterestCategoryNameEnum.TRANSPORTATIONS: + return PointOfInterestGroupEnum.PUBLIC_TRANSPORT + case PointOfInterestCategoryNameEnum.AMUSEMENT_PARK: + case PointOfInterestCategoryNameEnum.MUSEUM: + case PointOfInterestCategoryNameEnum.SPORTS: + case PointOfInterestCategoryNameEnum.THEATRE: + case PointOfInterestCategoryNameEnum.TOURIST: + case PointOfInterestCategoryNameEnum.ZOO: + return PointOfInterestGroupEnum.ATTRACTIONS + case PointOfInterestCategoryNameEnum.NEARBY_COMPANIES: + case PointOfInterestCategoryNameEnum.FAIR: + return PointOfInterestGroupEnum.BUSINESS + case PointOfInterestCategoryNameEnum.PARKING_GARAGE: + return PointOfInterestGroupEnum.PARKING + case PointOfInterestCategoryNameEnum.SHOPPING: + case PointOfInterestCategoryNameEnum.RESTAURANT: + return PointOfInterestGroupEnum.SHOPPING_DINING + case PointOfInterestCategoryNameEnum.HOSPITAL: default: - return null + return PointOfInterestGroupEnum.LOCATION } } diff --git a/types/components/icon.ts b/types/components/icon.ts index 6b11649a2..c0fdf6ee0 100644 --- a/types/components/icon.ts +++ b/types/components/icon.ts @@ -9,9 +9,11 @@ export interface IconProps export enum IconName { Accessibility = "Accessibility", AccountCircle = "AccountCircle", + Airplane = "Airplane", ArrowRight = "ArrowRight", Bar = "Bar", Biking = "Biking", + Business = "Business", Calendar = "Calendar", Camera = "Camera", Cellphone = "Cellphone", diff --git a/types/components/maps/poiMarker.ts b/types/components/maps/poiMarker.ts index 89932fb51..34fad0e6f 100644 --- a/types/components/maps/poiMarker.ts +++ b/types/components/maps/poiMarker.ts @@ -2,7 +2,14 @@ import { poiVariants } from "@/components/Maps/Markers/Poi/variants" import type { VariantProps } from "class-variance-authority" +import { + PointOfInterestCategoryNameEnum, + PointOfInterestGroupEnum, +} from "@/types/hotel" + export interface PoiMarkerProps extends VariantProps { + group: PointOfInterestGroupEnum + categoryName?: PointOfInterestCategoryNameEnum size?: number className?: string } diff --git a/types/hotel.ts b/types/hotel.ts index a2656f2b0..54d9c8125 100644 --- a/types/hotel.ts +++ b/types/hotel.ts @@ -20,4 +20,32 @@ export type HotelTripAdvisor = export type RoomData = z.infer export type PointOfInterest = z.output -export type PointOfInterestCategory = PointOfInterest["category"] + +export enum PointOfInterestCategoryNameEnum { + AIRPORT = "Airport", + AMUSEMENT_PARK = "Amusement park", + BUS_TERMINAL = "Bus terminal", + FAIR = "Fair", + HOSPITAL = "Hospital", + HOTEL = "Hotel", + MARKETING_CITY = "Marketing city", + MUSEUM = "Museum", + NEARBY_COMPANIES = "Nearby companies", + PARKING_GARAGE = "Parking / Garage", + RESTAURANT = "Restaurant", + SHOPPING = "Shopping", + SPORTS = "Sports", + THEATRE = "Theatre", + TOURIST = "Tourist", + TRANSPORTATIONS = "Transportations", + ZOO = "Zoo", +} + +export enum PointOfInterestGroupEnum { + PUBLIC_TRANSPORT = "Public transport", + ATTRACTIONS = "Attractions", + BUSINESS = "Business", + LOCATION = "Location", + PARKING = "Parking", + SHOPPING_DINING = "Shopping & Dining", +}