feat(SW-66, SW-348): search functionality and ui

This commit is contained in:
Simon Emanuelsson
2024-08-28 10:47:57 +02:00
parent b9dbcf7d90
commit af850c90e7
437 changed files with 7663 additions and 9881 deletions

View File

@@ -584,3 +584,192 @@ const rate = z.object({
export const getRatesSchema = z.array(rate)
export type Rate = z.infer<typeof rate>
const hotelFilter = z.object({
roomFacilities: z.array(z.string()),
hotelFacilities: z.array(z.string()),
hotelSurroundings: z.array(z.string()),
})
export const getFiltersSchema = hotelFilter
export type HotelFilter = z.infer<typeof hotelFilter>
export const apiCitiesByCountrySchema = z.object({
data: z.array(
z
.object({
attributes: z.object({
cityIdentifier: z.string().optional(),
name: z.string(),
keywords: z.array(z.string()).optional(),
timeZoneId: z.string().optional(),
ianaTimeZoneId: z.string().optional(),
isPublished: z.boolean().optional().default(false),
}),
id: z.string(),
type: z.literal("cities"),
})
.transform((data) => {
return {
...data.attributes,
id: data.id,
type: data.type,
}
})
),
})
export interface CitiesByCountry
extends z.output<typeof apiCitiesByCountrySchema> {}
export type CitiesGroupedByCountry = Record<string, CitiesByCountry["data"]>
export const apiCountriesSchema = z.object({
data: z
.array(
z.object({
attributes: z.object({
currency: z.string().optional(),
name: z.string(),
}),
hotelInformationSystemId: z.number().optional(),
id: z.string().optional(),
language: z.string().optional(),
type: z.literal("countries"),
})
)
.transform((data) => {
return data.map((country) => {
return {
...country.attributes,
hotelInformationSystemId: country.hotelInformationSystemId,
id: country.id,
language: country.language,
type: country.type,
}
})
}),
})
export interface Countries extends z.output<typeof apiCountriesSchema> {}
export const apiLocationCitySchema = z.object({
attributes: z.object({
cityIdentifier: z.string().optional(),
keyWords: z.array(z.string()).optional(),
name: z.string().optional().default(""),
}),
country: z.string().optional().default(""),
id: z.string().optional().default(""),
type: z.literal("cities"),
})
export const apiCitySchema = z
.object({
data: z.array(
z.object({
attributes: z.object({
cityIdentifier: z.string().optional(),
name: z.string(),
keywords: z.array(z.string()),
timeZoneId: z.string().optional(),
ianaTimeZoneId: z.string().optional(),
isPublished: z.boolean().optional().default(false),
}),
id: z.string().optional(),
type: z.literal("cities"),
})
),
})
.transform(({ data }) => {
if (data.length) {
const city = data[0]
return {
...city.attributes,
id: city.id,
type: city.type,
}
}
return null
})
export const apiLocationHotelSchema = z.object({
attributes: z.object({
distanceToCentre: z.number().optional(),
images: z
.object({
large: z.string().optional(),
medium: z.string().optional(),
small: z.string().optional(),
tiny: z.string().optional(),
})
.optional(),
keyWords: z.array(z.string()).optional(),
name: z.string().optional().default(""),
operaId: z.string().optional(),
}),
id: z.string().optional().default(""),
relationships: z
.object({
city: z
.object({
links: z
.object({
related: z.string().optional(),
})
.optional(),
})
.optional(),
})
.optional(),
type: z.literal("hotels"),
})
export const apiLocationsSchema = z.object({
data: z
.array(
z
.discriminatedUnion("type", [
apiLocationCitySchema,
apiLocationHotelSchema,
])
.transform((location) => {
if (location.type === "cities") {
return {
...location.attributes,
country: location?.country ?? "",
id: location.id,
type: location.type,
}
}
return {
...location.attributes,
id: location.id,
relationships: {
city: {
cityIdentifier: "",
ianaTimeZoneId: "",
id: "",
isPublished: false,
keywords: [],
name: "",
timeZoneId: "",
type: "cities",
url: location?.relationships?.city?.links?.related ?? "",
},
},
type: location.type,
}
})
)
.transform((data) =>
data
.filter((node) => !!node)
.sort((a, b) => {
if (a.type === b.type) {
return a.name.localeCompare(b.name)
} else {
return a.type === "cities" ? -1 : 1
}
})
),
})