@v-office/website-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +337 -0
- package/dist/client-BbAfk-qa.mjs +33672 -0
- package/dist/custom-attribute-ChCbJKf_.mjs +54 -0
- package/dist/errors-2cuUGSvi.mjs +5 -0
- package/dist/index.d.mts +16130 -0
- package/dist/index.mjs +3 -0
- package/dist/operations-BanW36PK.mjs +12616 -0
- package/dist/operations-CHxEQ3jG.mjs +904 -0
- package/dist/parser-D6UAf8Ld.mjs +65 -0
- package/dist/quote-C3HZsFua.mjs +313 -0
- package/dist/quote-Vl6Nutaa.mjs +513 -0
- package/dist/rentals-BFmmp26v.mjs +323 -0
- package/dist/rentals-cQAg5TTW.mjs +403 -0
- package/dist/search-JqA3v_Fx.mjs +342 -0
- package/dist/search-filter-metadata-DZP0-Udc.mjs +4294 -0
- package/dist/to-rental-highlights-BcRa9Odv.mjs +402 -0
- package/dist/translations/shared/de-DE/availability.json +15 -0
- package/dist/translations/shared/de-DE/booking.json +15 -0
- package/dist/translations/shared/de-DE/insurance.json +18 -0
- package/dist/translations/shared/de-DE/quote.json +8 -0
- package/dist/translations/shared/de-DE/reviews.json +11 -0
- package/dist/translations/shared/en-US/availability.json +15 -0
- package/dist/translations/shared/en-US/booking.json +15 -0
- package/dist/translations/shared/en-US/insurance.json +18 -0
- package/dist/translations/shared/en-US/quote.json +8 -0
- package/dist/translations/shared/en-US/reviews.json +11 -0
- package/dist/translations/v10/de-DE/core.json +7027 -0
- package/dist/translations/v10/en-US/core.json +7027 -0
- package/dist/translations/v9/de-DE/core.json +4 -0
- package/dist/translations/v9/de-DE/filter.json +25 -0
- package/dist/translations/v9/de-DE/rental-attribute-categories.json +19 -0
- package/dist/translations/v9/de-DE/rental-attributes.json +451 -0
- package/dist/translations/v9/en-US/core.json +4 -0
- package/dist/translations/v9/en-US/filter.json +25 -0
- package/dist/translations/v9/en-US/rental-attribute-categories.json +19 -0
- package/dist/translations/v9/en-US/rental-attributes.json +451 -0
- package/package.json +90 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { F as parseVofficeFacilityData, I as parseVofficeFeedbackData, L as parseVofficeUnitData, M as VofficeUnitDataPropertyCategoryLabelKeys, N as VofficeUnitDataPropertyCategoryValues, P as VofficeUnitDataPropertyMetadata } from "./client-BbAfk-qa.mjs";
|
|
2
|
+
import "./errors-2cuUGSvi.mjs";
|
|
3
|
+
import { c as localeToLanguage, s as makeTranslate } from "./parser-D6UAf8Ld.mjs";
|
|
4
|
+
import { i as renderLabeledAttributeValue, t as renderCustomAttributeHighlight } from "./custom-attribute-ChCbJKf_.mjs";
|
|
5
|
+
import { n as toAddress, r as toLocalizedString, t as toRentalHighlights } from "./to-rental-highlights-BcRa9Odv.mjs";
|
|
6
|
+
import { Effect } from "effect";
|
|
7
|
+
//#region src/adapters/v9/parser/rentals/to-description.ts
|
|
8
|
+
const toDescription = (data, locale) => {
|
|
9
|
+
const description = {};
|
|
10
|
+
const intro = toLocalizedString(data.known.intro, locale);
|
|
11
|
+
const headline = toLocalizedString(data.known.headline, locale);
|
|
12
|
+
const descriptionText = toLocalizedString(data.known.description, locale);
|
|
13
|
+
const altDescription = toLocalizedString(data.known.altDescription, locale);
|
|
14
|
+
const arrivalInfo = toLocalizedString(data.known.arrivalInfo, locale);
|
|
15
|
+
const departureInfo = toLocalizedString(data.known.departureInfo, locale);
|
|
16
|
+
const locationDescription = toLocalizedString(data.known.locationDescription, locale);
|
|
17
|
+
const directions = toLocalizedString(data.known.directions, locale);
|
|
18
|
+
if (intro != null) description.intro = intro;
|
|
19
|
+
if (headline != null) description.headline = headline;
|
|
20
|
+
if (descriptionText != null) description.description = descriptionText;
|
|
21
|
+
if (altDescription != null) description.altDescription = altDescription;
|
|
22
|
+
if (arrivalInfo != null) description.arrivalInfo = arrivalInfo;
|
|
23
|
+
if (departureInfo != null) description.departureInfo = departureInfo;
|
|
24
|
+
if (locationDescription != null) description.locationDescription = locationDescription;
|
|
25
|
+
if (directions != null) description.directions = directions;
|
|
26
|
+
return description;
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/adapters/v9/parser/rentals/to-image.ts
|
|
30
|
+
const IMAGE_ASPECT_RATIO = 3 / 2;
|
|
31
|
+
const IMAGE_SRCSET_WIDTHS = [
|
|
32
|
+
320,
|
|
33
|
+
480,
|
|
34
|
+
640,
|
|
35
|
+
960,
|
|
36
|
+
1280,
|
|
37
|
+
1920,
|
|
38
|
+
2560
|
|
39
|
+
];
|
|
40
|
+
const IMAGE_DEFAULT_WIDTH = 960;
|
|
41
|
+
const buildImageUrl = (imageProxyBaseUrl, path, width) => {
|
|
42
|
+
const base = imageProxyBaseUrl.replace(/\/$/, "");
|
|
43
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
44
|
+
return `${base}/_/rs:fill:${width}:${Math.round(width / IMAGE_ASPECT_RATIO)}:0/plain/${normalizedPath}`;
|
|
45
|
+
};
|
|
46
|
+
const buildSrcset = (imageProxyBaseUrl, path) => IMAGE_SRCSET_WIDTHS.map((width) => `${buildImageUrl(imageProxyBaseUrl, path, width)} ${width}w`).join(", ");
|
|
47
|
+
const isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
|
|
48
|
+
const toDataImageId = (dataImage) => dataImage?.id?.toString();
|
|
49
|
+
const getImagePath = (entry) => entry.image?.path ?? entry.normalizedPath;
|
|
50
|
+
const getFileName = (path) => path?.split("/").at(-1);
|
|
51
|
+
const getDirectoryName = (path) => {
|
|
52
|
+
const lastSlashIndex = path.lastIndexOf("/");
|
|
53
|
+
return lastSlashIndex === -1 ? void 0 : path.slice(0, lastSlashIndex);
|
|
54
|
+
};
|
|
55
|
+
const stripDataImageFilePrefix = (fileName) => fileName.replace(/^mf(?=\d)/i, "");
|
|
56
|
+
const getDataImageFileName = (dataImage) => {
|
|
57
|
+
const name = dataImage.name != null ? stripDataImageFilePrefix(dataImage.name) : void 0;
|
|
58
|
+
if (name != null) return name;
|
|
59
|
+
return dataImage.id != null ? `${dataImage.id}.jpg` : void 0;
|
|
60
|
+
};
|
|
61
|
+
const normalizeDataImagePath = (dataImage, vofficeImages) => {
|
|
62
|
+
const fileName = getDataImageFileName(dataImage);
|
|
63
|
+
if (fileName == null) return void 0;
|
|
64
|
+
const matchingPath = vofficeImages.find((image) => getFileName(image.path ?? void 0) === fileName)?.path;
|
|
65
|
+
if (matchingPath != null) return matchingPath;
|
|
66
|
+
const directoryName = vofficeImages.map((image) => image.path != null ? getDirectoryName(image.path) : void 0).find((path) => path != null);
|
|
67
|
+
return directoryName != null ? `${directoryName}/${fileName}` : void 0;
|
|
68
|
+
};
|
|
69
|
+
const pathMatchesName = (path, name) => path != null && name != null && (path === name || path.endsWith(`/${name}`));
|
|
70
|
+
const entriesShareId = (left, right) => {
|
|
71
|
+
const leftIds = [left.image?.id, toDataImageId(left.dataImage)].filter(isNonEmptyString);
|
|
72
|
+
const rightIds = [right.image?.id, toDataImageId(right.dataImage)].filter(isNonEmptyString);
|
|
73
|
+
return leftIds.some((leftId) => rightIds.includes(leftId));
|
|
74
|
+
};
|
|
75
|
+
const entriesSharePathOrName = (left, right) => {
|
|
76
|
+
const leftPath = getImagePath(left);
|
|
77
|
+
const rightPath = getImagePath(right);
|
|
78
|
+
const leftName = left.dataImage != null ? getDataImageFileName(left.dataImage) : getFileName(left.image?.path ?? void 0);
|
|
79
|
+
const rightName = right.dataImage != null ? getDataImageFileName(right.dataImage) : getFileName(right.image?.path ?? void 0);
|
|
80
|
+
return leftPath != null && rightPath != null && leftPath === rightPath || pathMatchesName(leftPath, rightName) || pathMatchesName(rightPath, leftName);
|
|
81
|
+
};
|
|
82
|
+
const entriesMatch = (left, right) => entriesShareId(left, right) || entriesSharePathOrName(left, right);
|
|
83
|
+
const mergeEntry = (existing, next) => {
|
|
84
|
+
const image = existing.image ?? next.image;
|
|
85
|
+
const dataImage = existing.dataImage ?? next.dataImage;
|
|
86
|
+
const normalizedPath = existing.normalizedPath ?? next.normalizedPath;
|
|
87
|
+
const entry = { source: existing.source };
|
|
88
|
+
if (image != null) entry.image = image;
|
|
89
|
+
if (dataImage != null) entry.dataImage = dataImage;
|
|
90
|
+
if (normalizedPath != null) entry.normalizedPath = normalizedPath;
|
|
91
|
+
return entry;
|
|
92
|
+
};
|
|
93
|
+
const mergeImageEntries = (entries) => {
|
|
94
|
+
const merged = [];
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const index = merged.findIndex((existing) => entriesMatch(existing, entry));
|
|
97
|
+
if (index === -1) {
|
|
98
|
+
merged.push(entry);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
merged[index] = mergeEntry(merged[index], entry);
|
|
102
|
+
}
|
|
103
|
+
return merged;
|
|
104
|
+
};
|
|
105
|
+
const getImageEntries = (rental, data) => {
|
|
106
|
+
const vofficeImages = rental.voffice_images ?? [];
|
|
107
|
+
return [
|
|
108
|
+
...vofficeImages.map((image) => ({
|
|
109
|
+
source: "voffice_images",
|
|
110
|
+
image
|
|
111
|
+
})),
|
|
112
|
+
...(rental.voffice_room_images ?? []).map((image) => ({
|
|
113
|
+
source: "voffice_room_images",
|
|
114
|
+
image
|
|
115
|
+
})),
|
|
116
|
+
...(data.known.images ?? []).flatMap((dataImage) => {
|
|
117
|
+
const normalizedPath = normalizeDataImagePath(dataImage, vofficeImages);
|
|
118
|
+
if (normalizedPath == null) return [];
|
|
119
|
+
return [{
|
|
120
|
+
source: "data_images",
|
|
121
|
+
dataImage,
|
|
122
|
+
normalizedPath
|
|
123
|
+
}];
|
|
124
|
+
})
|
|
125
|
+
];
|
|
126
|
+
};
|
|
127
|
+
const toImage = (imageProxyBaseUrl, entry, locale) => {
|
|
128
|
+
const path = getImagePath(entry);
|
|
129
|
+
const src = path != null ? buildImageUrl(imageProxyBaseUrl, path, IMAGE_DEFAULT_WIDTH) : "";
|
|
130
|
+
const srcset = path != null ? buildSrcset(imageProxyBaseUrl, path) : "";
|
|
131
|
+
const title = toLocalizedString(entry.dataImage?.titles, locale) ?? entry.image?.title;
|
|
132
|
+
const alt = title ?? entry.image?.description ?? "";
|
|
133
|
+
const metadata = { source: entry.source };
|
|
134
|
+
if (entry.dataImage != null) metadata.dataImage = entry.dataImage;
|
|
135
|
+
const image = {
|
|
136
|
+
idOrPath: path ?? toDataImageId(entry.dataImage) ?? entry.dataImage?.name ?? "",
|
|
137
|
+
src,
|
|
138
|
+
srcset,
|
|
139
|
+
alt,
|
|
140
|
+
metadata
|
|
141
|
+
};
|
|
142
|
+
if (title != null) image.title = title;
|
|
143
|
+
if (entry.dataImage?.tag != null) image.category = entry.dataImage.tag;
|
|
144
|
+
return image;
|
|
145
|
+
};
|
|
146
|
+
const toImages = (imageProxyBaseUrl, rental, locale, data) => {
|
|
147
|
+
if (rental.voffice_images == null || rental.voffice_images.length === 0) return [];
|
|
148
|
+
return mergeImageEntries(getImageEntries(rental, data)).map((entry) => toImage(imageProxyBaseUrl, entry, locale));
|
|
149
|
+
};
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/adapters/v9/parser/rentals/to-location.ts
|
|
152
|
+
const toLocation = (location) => {
|
|
153
|
+
if (location == null) return void 0;
|
|
154
|
+
const [longitude, latitude] = location.coordinates;
|
|
155
|
+
return {
|
|
156
|
+
latitude,
|
|
157
|
+
longitude
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/adapters/v9/parser/rentals/to-property.ts
|
|
162
|
+
const toProperty = (facility, locale) => {
|
|
163
|
+
const data = parseVofficeFacilityData(facility.data);
|
|
164
|
+
const name = toLocalizedString(data.known.name, locale);
|
|
165
|
+
const description = toLocalizedString(data.known.description, locale);
|
|
166
|
+
const property = {
|
|
167
|
+
id: facility.id,
|
|
168
|
+
nameOrLabel: name ?? facility.name
|
|
169
|
+
};
|
|
170
|
+
if (description != null) property.description = { description };
|
|
171
|
+
return property;
|
|
172
|
+
};
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/adapters/v9/parser/rentals/to-rental-attributes.ts
|
|
175
|
+
const GENERAL_CATEGORY$1 = {
|
|
176
|
+
key: "GENERAL",
|
|
177
|
+
labelKey: VofficeUnitDataPropertyCategoryLabelKeys.GENERAL
|
|
178
|
+
};
|
|
179
|
+
const CATEGORY_ORDER = new Map(VofficeUnitDataPropertyCategoryValues.map((category, index) => [category, index]));
|
|
180
|
+
const PROPERTY_METADATA_ENTRIES = Object.entries(VofficeUnitDataPropertyMetadata).map(([key, metadata], index) => ({
|
|
181
|
+
key,
|
|
182
|
+
metadata,
|
|
183
|
+
index
|
|
184
|
+
})).filter(({ metadata }) => metadata.category.key !== "LOCATION").sort((left, right) => {
|
|
185
|
+
return (CATEGORY_ORDER.get(left.metadata.category.key) ?? Number.MAX_SAFE_INTEGER) - (CATEGORY_ORDER.get(right.metadata.category.key) ?? Number.MAX_SAFE_INTEGER) || left.index - right.index;
|
|
186
|
+
});
|
|
187
|
+
const toRentalAttributes = ({ locale, translations, attributes, customAttributeFilterDefinitions }) => Effect.gen(function* () {
|
|
188
|
+
const result = [];
|
|
189
|
+
const categoriesByKey = /* @__PURE__ */ new Map();
|
|
190
|
+
const subCategoriesByKey = /* @__PURE__ */ new Map();
|
|
191
|
+
const knownAttributes = attributes.known;
|
|
192
|
+
const translate = makeTranslate(translations, locale);
|
|
193
|
+
const getGeneralSubCategory = () => Effect.gen(function* () {
|
|
194
|
+
let category = categoriesByKey.get(GENERAL_CATEGORY$1.key);
|
|
195
|
+
if (category == null) {
|
|
196
|
+
category = {
|
|
197
|
+
label: yield* translate(GENERAL_CATEGORY$1.labelKey, GENERAL_CATEGORY$1.key),
|
|
198
|
+
subCategories: []
|
|
199
|
+
};
|
|
200
|
+
categoriesByKey.set(GENERAL_CATEGORY$1.key, category);
|
|
201
|
+
result.push(category);
|
|
202
|
+
}
|
|
203
|
+
let subCategory = subCategoriesByKey.get(GENERAL_CATEGORY$1.key);
|
|
204
|
+
if (subCategory == null) {
|
|
205
|
+
subCategory = {
|
|
206
|
+
label: category.label,
|
|
207
|
+
items: []
|
|
208
|
+
};
|
|
209
|
+
subCategoriesByKey.set(GENERAL_CATEGORY$1.key, subCategory);
|
|
210
|
+
category.subCategories.push(subCategory);
|
|
211
|
+
}
|
|
212
|
+
return subCategory;
|
|
213
|
+
});
|
|
214
|
+
for (const { key, metadata } of PROPERTY_METADATA_ENTRIES) {
|
|
215
|
+
const attribute = renderLabeledAttributeValue({
|
|
216
|
+
key,
|
|
217
|
+
label: yield* translate(metadata.labelKey, key),
|
|
218
|
+
locale,
|
|
219
|
+
value: knownAttributes[key]
|
|
220
|
+
});
|
|
221
|
+
if (attribute == null) continue;
|
|
222
|
+
const categoryMetadata = metadata.category ?? GENERAL_CATEGORY$1;
|
|
223
|
+
let category = categoriesByKey.get(categoryMetadata.key);
|
|
224
|
+
if (category == null) {
|
|
225
|
+
category = {
|
|
226
|
+
label: yield* translate(categoryMetadata.labelKey, categoryMetadata.key),
|
|
227
|
+
subCategories: []
|
|
228
|
+
};
|
|
229
|
+
categoriesByKey.set(categoryMetadata.key, category);
|
|
230
|
+
result.push(category);
|
|
231
|
+
}
|
|
232
|
+
let subCategory = subCategoriesByKey.get(categoryMetadata.key);
|
|
233
|
+
if (subCategory == null) {
|
|
234
|
+
subCategory = {
|
|
235
|
+
label: yield* translate(GENERAL_CATEGORY$1.labelKey, GENERAL_CATEGORY$1.key),
|
|
236
|
+
items: []
|
|
237
|
+
};
|
|
238
|
+
subCategoriesByKey.set(categoryMetadata.key, subCategory);
|
|
239
|
+
category.subCategories.push(subCategory);
|
|
240
|
+
}
|
|
241
|
+
subCategory.items.push(attribute);
|
|
242
|
+
}
|
|
243
|
+
const customAttributeItems = [];
|
|
244
|
+
for (const definition of customAttributeFilterDefinitions) {
|
|
245
|
+
const value = knownAttributes[definition.key] ?? attributes.unknown[definition.key];
|
|
246
|
+
const attribute = renderCustomAttributeHighlight({
|
|
247
|
+
definitions: customAttributeFilterDefinitions,
|
|
248
|
+
key: definition.key,
|
|
249
|
+
locale,
|
|
250
|
+
value
|
|
251
|
+
});
|
|
252
|
+
if (attribute != null) customAttributeItems.push(attribute);
|
|
253
|
+
}
|
|
254
|
+
if (customAttributeItems.length > 0) (yield* getGeneralSubCategory()).items.push(...customAttributeItems);
|
|
255
|
+
return result;
|
|
256
|
+
});
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/adapters/v9/parser/rentals/to-rental-type.ts
|
|
259
|
+
const toRentalType = ({ translations, locale, rentalType }) => makeTranslate(translations, locale)(`Rental.rentalType.option.${rentalType}`, rentalType);
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/adapters/v9/parser/rentals/to-rental-vicinity.ts
|
|
262
|
+
const GENERAL_CATEGORY = {
|
|
263
|
+
key: "GENERAL",
|
|
264
|
+
labelKey: VofficeUnitDataPropertyCategoryLabelKeys.GENERAL
|
|
265
|
+
};
|
|
266
|
+
const LOCATION_METADATA_ENTRIES = Object.entries(VofficeUnitDataPropertyMetadata).map(([key, metadata], index) => ({
|
|
267
|
+
key,
|
|
268
|
+
metadata,
|
|
269
|
+
index
|
|
270
|
+
})).filter(({ metadata }) => metadata.category.key === "LOCATION").sort((left, right) => left.index - right.index);
|
|
271
|
+
const toRentalVicinity = ({ locale, translations, attributes }) => Effect.gen(function* () {
|
|
272
|
+
const items = [];
|
|
273
|
+
const knownAttributes = attributes.known;
|
|
274
|
+
const translate = makeTranslate(translations, locale);
|
|
275
|
+
for (const { key, metadata } of LOCATION_METADATA_ENTRIES) {
|
|
276
|
+
const item = renderLabeledAttributeValue({
|
|
277
|
+
key,
|
|
278
|
+
label: yield* translate(metadata.labelKey, key),
|
|
279
|
+
locale,
|
|
280
|
+
value: knownAttributes[key]
|
|
281
|
+
});
|
|
282
|
+
if (item != null) items.push(item);
|
|
283
|
+
}
|
|
284
|
+
if (items.length === 0) return [];
|
|
285
|
+
return [{
|
|
286
|
+
label: yield* translate(GENERAL_CATEGORY.labelKey, GENERAL_CATEGORY.key),
|
|
287
|
+
items
|
|
288
|
+
}];
|
|
289
|
+
});
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region src/adapters/v9/parser/rentals/to-reviews.ts
|
|
292
|
+
const toClassification = (rating) => {
|
|
293
|
+
if (rating >= 4.5) return "excellent";
|
|
294
|
+
if (rating >= 4) return "very-good";
|
|
295
|
+
if (rating >= 3) return "good";
|
|
296
|
+
if (rating >= 2) return "fair";
|
|
297
|
+
return "poor";
|
|
298
|
+
};
|
|
299
|
+
const roundRatingUp = (rating) => Math.ceil(Number(rating.toFixed(6)) * 10) / 10;
|
|
300
|
+
const renderTemplate = (template, values) => Object.entries(values).reduce((result, [key, value]) => result.replaceAll(`{${key}}`, value), template);
|
|
301
|
+
const toTravelDate = (locale, value) => {
|
|
302
|
+
if (value == null) return void 0;
|
|
303
|
+
return new Intl.DateTimeFormat(locale, {
|
|
304
|
+
month: "long",
|
|
305
|
+
year: "numeric"
|
|
306
|
+
}).format(new Date(value));
|
|
307
|
+
};
|
|
308
|
+
const toReviews = ({ locale, translations, rental }) => Effect.gen(function* () {
|
|
309
|
+
const parsedItems = (yield* Effect.succeed(rental.voffice_feedbacks))?.flatMap((feedback) => {
|
|
310
|
+
const { forename, surname, avgRating, text, highlighted, arrival, departure, onDate, onTimestamp } = parseVofficeFeedbackData(feedback.data).known;
|
|
311
|
+
const author = [forename, surname].filter((value) => value != null && value !== "").join(" ");
|
|
312
|
+
if (author === "" || avgRating == null || avgRating < 1 || text == null) return [];
|
|
313
|
+
return [{
|
|
314
|
+
rating: roundRatingUp(avgRating),
|
|
315
|
+
author,
|
|
316
|
+
text,
|
|
317
|
+
highlighted: highlighted === true,
|
|
318
|
+
travelDate: toTravelDate(locale, arrival ?? departure ?? onDate ?? onTimestamp)
|
|
319
|
+
}];
|
|
320
|
+
}) ?? [];
|
|
321
|
+
if (parsedItems.length === 0) return void 0;
|
|
322
|
+
const summaryRating = roundRatingUp(parsedItems.reduce((ratingSum, item) => ratingSum + item.rating, 0) / parsedItems.length);
|
|
323
|
+
const summaryRatingTemplate = yield* translations.translate(locale, "reviews.summary.rating");
|
|
324
|
+
const summaryCountTemplate = yield* translations.translate(locale, "reviews.summary.count");
|
|
325
|
+
const classification = toClassification(summaryRating);
|
|
326
|
+
const summary = {
|
|
327
|
+
rating: renderTemplate(summaryRatingTemplate, {
|
|
328
|
+
rating: summaryRating.toString(),
|
|
329
|
+
maxRating: "5"
|
|
330
|
+
}),
|
|
331
|
+
count: renderTemplate(summaryCountTemplate, { count: parsedItems.length.toString() }),
|
|
332
|
+
classification: yield* translations.translate(locale, `reviews.summary.classification.${classification}`)
|
|
333
|
+
};
|
|
334
|
+
const authorTemplate = yield* translations.translate(locale, "reviews.item.author");
|
|
335
|
+
const authorWithDateTemplate = yield* translations.translate(locale, "reviews.item.authorWithDate");
|
|
336
|
+
return {
|
|
337
|
+
items: parsedItems.sort((left, right) => Number(right.highlighted) - Number(left.highlighted)).map(({ highlighted: _highlighted, rating, author, travelDate, ...item }) => ({
|
|
338
|
+
...item,
|
|
339
|
+
author: travelDate == null ? renderTemplate(authorTemplate, { author }) : renderTemplate(authorWithDateTemplate, {
|
|
340
|
+
author,
|
|
341
|
+
date: travelDate
|
|
342
|
+
}),
|
|
343
|
+
rating: rating.toString()
|
|
344
|
+
})),
|
|
345
|
+
summary
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/adapters/v9/parser/rentals/to-rental-list-item.ts
|
|
350
|
+
const toRentalRentalsOutput = ({ rental, locale, translations, imageProxyBaseUrl, rentalHighlightPrioritization, customAttributeFilterDefinitions }) => Effect.gen(function* () {
|
|
351
|
+
const data = parseVofficeUnitData(rental.data);
|
|
352
|
+
const rawRentalType = data.known.type?.trim();
|
|
353
|
+
const translatedRentalType = rawRentalType != null && rawRentalType.length > 0 ? yield* toRentalType({
|
|
354
|
+
locale,
|
|
355
|
+
translations,
|
|
356
|
+
rentalType: rawRentalType
|
|
357
|
+
}) : void 0;
|
|
358
|
+
const address = toAddress(data, locale);
|
|
359
|
+
const description = toDescription(data, locale);
|
|
360
|
+
const images = toImages(imageProxyBaseUrl, rental, locale, data);
|
|
361
|
+
const location = toLocation(data.known.loc);
|
|
362
|
+
const attributes = yield* toRentalAttributes({
|
|
363
|
+
locale,
|
|
364
|
+
translations,
|
|
365
|
+
attributes: data,
|
|
366
|
+
customAttributeFilterDefinitions
|
|
367
|
+
});
|
|
368
|
+
const vicinity = yield* toRentalVicinity({
|
|
369
|
+
locale,
|
|
370
|
+
translations,
|
|
371
|
+
attributes: data
|
|
372
|
+
});
|
|
373
|
+
const highlights = yield* toRentalHighlights({
|
|
374
|
+
locale,
|
|
375
|
+
translations,
|
|
376
|
+
highlightPrioritization: rentalHighlightPrioritization,
|
|
377
|
+
customAttributeFilterDefinitions,
|
|
378
|
+
attributes: data
|
|
379
|
+
});
|
|
380
|
+
const reviews = yield* toReviews({
|
|
381
|
+
locale,
|
|
382
|
+
translations,
|
|
383
|
+
rental
|
|
384
|
+
});
|
|
385
|
+
const item = {
|
|
386
|
+
id: rental.voffice_id.toString(),
|
|
387
|
+
nameOrLabel: typeof data.known.name === "string" ? data.known.name : rental.name,
|
|
388
|
+
timeZone: "Europe/Berlin"
|
|
389
|
+
};
|
|
390
|
+
if (translatedRentalType != null) item.rentalType = translatedRentalType;
|
|
391
|
+
if (location != null) item.location = location;
|
|
392
|
+
if (Object.keys(address).length > 0) item.address = address;
|
|
393
|
+
if (Object.keys(description).length > 0) item.description = description;
|
|
394
|
+
if (images.length > 0) item.images = images;
|
|
395
|
+
if (attributes != null) item.attributes = attributes;
|
|
396
|
+
if (vicinity != null) item.vicinity = vicinity;
|
|
397
|
+
if (highlights != null) item.highlights = highlights;
|
|
398
|
+
if (rental.voffice_facility != null) item.property = toProperty(rental.voffice_facility, locale);
|
|
399
|
+
if (reviews != null) item.reviews = reviews;
|
|
400
|
+
return item;
|
|
401
|
+
});
|
|
402
|
+
//#endregion
|
|
403
|
+
export { localeToLanguage, toRentalRentalsOutput };
|