@odynn/awayz-hotels 0.2.19 → 0.2.21

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.
@@ -0,0 +1,13 @@
1
+ import { ESearchType as o } from "../services/hotel/HotelService.types.js";
2
+ const t = {
3
+ [o.COUNTRY]: 1,
4
+ [o.CITY]: 2,
5
+ [o.REGION]: 3,
6
+ [o.LANDMARK]: 4,
7
+ [o.HOTEL]: 5,
8
+ [o.AIRPORT]: 6
9
+ }, e = 60;
10
+ export {
11
+ t as defaultLocationSortOrder,
12
+ e as defaultSimilarityThreshold
13
+ };
@@ -0,0 +1,5 @@
1
+ import { defaultLocationSortOrder as t, defaultSimilarityThreshold as e } from "./defaults.js";
2
+ export {
3
+ t as defaultLocationSortOrder,
4
+ e as defaultSimilarityThreshold
5
+ };
@@ -0,0 +1,4 @@
1
+ var E = /* @__PURE__ */ ((C) => (C.LOCATIONS = "LOCATIONS", C.CHECK_USER = "CHECK_USER", C.USER_REGIONS = "USER_REGIONS", C.CONVERT_CURRENCY = "CONVERT_CURRENCY", C.CLIENT_COMPONENT_KEY = "CLIENT_COMPONENT_KEY", C.SEARCH_LIMIT = "SEARCH_LIMIT", C))(E || {});
2
+ export {
3
+ E
4
+ };
@@ -1,14 +1,14 @@
1
- import { useMutation as u } from "@tanstack/react-query";
2
- import { HotelService as a } from "../../services/hotel/HotelService.js";
3
- import { ESearchType as I } from "../../services/hotel/HotelService.types.js";
1
+ import { useMutation as h } from "@tanstack/react-query";
2
+ import { HotelService as u } from "../../services/hotel/HotelService.js";
3
+ import { ESearchType as _ } from "../../services/hotel/HotelService.types.js";
4
4
  import { HotelChains as t } from "../../definitions/HotelChains.js";
5
5
  import { h as c } from "../../moment-BGjjqtLQ.js";
6
- import f from "../../stores/useHotelsStore.js";
7
- import { useAwayzContext as w, awayzClient as l } from "@odynn/awayz-core";
6
+ import D from "../../stores/useHotelsStore.js";
7
+ import { useAwayzContext as E, awayzClient as a } from "@odynn/awayz-core";
8
8
  import "../../arrayExtensions-CFEBYUok.js";
9
+ import { E as l } from "../../enums-BIly_FuI.js";
9
10
  import "react";
10
- var s = /* @__PURE__ */ ((o) => (o.CHECK_USER = "CHECK_USER", o.USER_REGIONS = "USER_REGIONS", o.CONVERT_CURRENCY = "CONVERT_CURRENCY", o.CLIENT_COMPONENT_KEY = "CLIENT_COMPONENT_KEY", o.SEARCH_LIMIT = "SEARCH_LIMIT", o))(s || {});
11
- const D = (o) => {
11
+ const I = (o) => {
12
12
  if (!o.checkinDate || !o.checkoutDate)
13
13
  throw new Error("Checkin and checkout dates are required");
14
14
  if (!o.coordinates)
@@ -21,7 +21,7 @@ const D = (o) => {
21
21
  )}`
22
22
  );
23
23
  });
24
- }, y = (o) => {
24
+ }, C = (o) => {
25
25
  if (!o.checkinDate || !o.checkoutDate)
26
26
  throw new Error("Checkin and checkout dates are required");
27
27
  if (!o.hotelId)
@@ -32,15 +32,15 @@ const D = (o) => {
32
32
  throw new Error(
33
33
  `Invalid hotel group: ${o.hotelGroup}. Please use one of the following: ${t.toList().join(", ")}`
34
34
  );
35
- }, U = () => {
36
- const { setHotels: o, hotels: r, setSearchParams: h } = f(), { config: i } = w(), {
35
+ }, $ = () => {
36
+ const { setHotels: o, hotels: r, setSearchParams: s } = D(), { config: i } = E(), {
37
37
  mutate: d,
38
- status: E,
39
- isError: _,
40
- error: S
41
- } = u({
38
+ status: m,
39
+ isError: p,
40
+ error: y
41
+ } = h({
42
42
  mutationFn: async (e) => {
43
- D(e), o([]), h({
43
+ I(e), o([]), s({
44
44
  checkinDate: c(e.checkinDate),
45
45
  checkoutDate: c(e.checkoutDate),
46
46
  guests: e.guests || 2,
@@ -58,25 +58,25 @@ const D = (o) => {
58
58
  search_range: e.searchRange || 10,
59
59
  range_type: e.rangeType || "mi",
60
60
  hotel_groups: e.hotelGroups || t.toList(),
61
- type: e.searchType || I.CITY,
61
+ type: e.searchType || _.CITY,
62
62
  external_inventory: (i == null ? void 0 : i.externalInventory) || !1
63
63
  };
64
- return await a.searchByCoords(n);
64
+ return await u.searchByCoords(n);
65
65
  },
66
66
  onSuccess: (e) => {
67
67
  e.success && o(e.data);
68
68
  },
69
69
  onSettled: () => {
70
- l.invalidateQueries({ queryKey: [s.SEARCH_LIMIT] });
70
+ a.invalidateQueries({ queryKey: [l.SEARCH_LIMIT] });
71
71
  }
72
72
  }), {
73
- mutate: m,
74
- status: p,
75
- isError: C,
76
- error: k
77
- } = u({
73
+ mutate: k,
74
+ status: f,
75
+ isError: S,
76
+ error: w
77
+ } = h({
78
78
  mutationFn: async (e) => {
79
- y(e), o([]), h({
79
+ C(e), o([]), s({
80
80
  checkinDate: c(e.checkinDate),
81
81
  checkoutDate: c(e.checkoutDate),
82
82
  guests: e.guests || 2,
@@ -92,26 +92,26 @@ const D = (o) => {
92
92
  cash_or_points: e.cashOrPoints || ["cash", "points"],
93
93
  hotel_group: e.hotelGroup
94
94
  };
95
- return await a.searchByHotelId(n);
95
+ return await u.searchByHotelId(n);
96
96
  },
97
97
  onSuccess: (e) => {
98
98
  e.success && o(e.data);
99
99
  },
100
100
  onSettled: () => {
101
- l.invalidateQueries({ queryKey: [s.SEARCH_LIMIT] });
101
+ a.invalidateQueries({ queryKey: [l.SEARCH_LIMIT] });
102
102
  }
103
103
  });
104
104
  return {
105
105
  results: r,
106
- loading: E === "pending" || p === "pending",
107
- isCoordsSearchError: _,
108
- coordsSearchError: S,
109
- isHotelIdSearchError: C,
110
- hotelIdSearchError: k,
106
+ loading: m === "pending" || f === "pending",
107
+ isCoordsSearchError: p,
108
+ coordsSearchError: y,
109
+ isHotelIdSearchError: S,
110
+ hotelIdSearchError: w,
111
111
  searchByCoords: d,
112
- searchByHotelId: m
112
+ searchByHotelId: k
113
113
  };
114
114
  };
115
115
  export {
116
- U as useHotelSearch
116
+ $ as useHotelSearch
117
117
  };
@@ -1,30 +1,40 @@
1
- import { useQuery as i } from "@tanstack/react-query";
2
- import { HotelService as n } from "../../services/hotel/HotelService.js";
1
+ import { useQuery as a } from "@tanstack/react-query";
2
+ import { HotelService as m } from "../../services/hotel/HotelService.js";
3
3
  import "../../moment-BGjjqtLQ.js";
4
4
  import "../../arrayExtensions-CFEBYUok.js";
5
- import { useState as c, useEffect as a } from "react";
6
- const m = 500, u = (t, o = m) => {
7
- const [e, r] = c(t);
8
- return a(() => {
9
- const s = setTimeout(() => {
5
+ import { E as u } from "../../enums-BIly_FuI.js";
6
+ import { useState as l, useEffect as d } from "react";
7
+ import { defaultSimilarityThreshold as L, defaultLocationSortOrder as f } from "../../configs/defaults.js";
8
+ import { sortLocationResults as p } from "../../utilities/hotelUtils/hotelUtils.js";
9
+ const y = 500, E = (t, e = y) => {
10
+ const [s, r] = l(t);
11
+ return d(() => {
12
+ const o = setTimeout(() => {
10
13
  r(t);
11
- }, o);
14
+ }, e);
12
15
  return () => {
13
- clearTimeout(s);
16
+ clearTimeout(o);
14
17
  };
15
- }, [t, o]), e;
16
- }, d = (t) => {
17
- const o = u(t), { data: e, isLoading: r } = i({
18
- queryKey: ["locations", o],
19
- queryFn: () => n.getLocations(t),
18
+ }, [t, e]), s;
19
+ }, C = (t, e = L, s = f) => {
20
+ const r = E(t), { data: o, isLoading: i } = a({
21
+ queryKey: [u.LOCATIONS, r],
22
+ queryFn: () => m.getLocations(t),
20
23
  enabled: !!t
21
24
  // Only run the query if searchInput is not empty
22
- });
25
+ }), n = (o == null ? void 0 : o.data) || [];
23
26
  return {
24
- locations: (e == null ? void 0 : e.data) || [],
25
- loading: r
27
+ locations: p(
28
+ t,
29
+ e,
30
+ s,
31
+ n
32
+ ).map(
33
+ ({ score: R, startsWithText: O, ...c }) => c
34
+ ),
35
+ loading: i
26
36
  };
27
37
  };
28
38
  export {
29
- d as useLocationSearch
39
+ C as useLocationSearch
30
40
  };
@@ -0,0 +1,9 @@
1
+ export declare const defaultLocationSortOrder: {
2
+ readonly "Country Search": 1;
3
+ readonly "City Search": 2;
4
+ readonly "Region Search": 3;
5
+ readonly "Landmark Search": 4;
6
+ readonly "Hotel Search": 5;
7
+ readonly "Airport Search": 6;
8
+ };
9
+ export declare const defaultSimilarityThreshold = 60;
@@ -0,0 +1 @@
1
+ export { defaultSimilarityThreshold, defaultLocationSortOrder } from './defaults';
@@ -2,9 +2,13 @@ import { IUseLocationSearchResponse } from './useLocationSearch.types';
2
2
  /**
3
3
  * Awayz hook to search for locations based on the provided search input.
4
4
  *
5
- * @param {string} searchInput - The input string to search for locations.
5
+ * @param {string} searchInput - The input to search for locations.
6
+ * @param {number} [similarityThreshold=defaultSimilarityThreshold] - The threshold for similarity in location names.
7
+ * @param {Record<string, number>} [locationSortOrder=defaultLocationSortOrder] - The sort order for the locations.
8
+ *
6
9
  * @returns {IUseLocationSearchResponse} An object containing the search results and loading state.
7
10
  * @returns {Array} return.locations - The array of locations matching the search input.
8
11
  * @returns {boolean} return.loading - The loading state of the query.
9
12
  */
10
- export declare const useLocationSearch: (searchInput: string) => IUseLocationSearchResponse;
13
+ export declare const useLocationSearch: (searchInput: string, similarityThreshold?: number, // Default threshold for similarity,
14
+ locationSortOrder?: Record<string, number>) => IUseLocationSearchResponse;
@@ -5,4 +5,5 @@ export { ESearchType } from './services/hotel/HotelService.types';
5
5
  export * from './components';
6
6
  export * from './hooks';
7
7
  export * from './enums';
8
+ export * from './configs';
8
9
  export type { IRoom, IRate, IHotelDetails, IPointsAsCash };
@@ -147,7 +147,7 @@ export interface IRate {
147
147
  quantityAvailable: number;
148
148
  publicAmount?: number;
149
149
  dealTypes?: string;
150
- cancellationTimeline: string[];
150
+ cancellationTimeline: ICancellationTimeline[];
151
151
  boardType: string;
152
152
  supportedLoyaltyProgramme?: string;
153
153
  availablePaymentMethods: string[];
@@ -201,4 +201,9 @@ interface IAddress {
201
201
  countryCode: string;
202
202
  region: string | null;
203
203
  }
204
+ interface ICancellationTimeline {
205
+ before: string;
206
+ currency: string;
207
+ refundAmount: string;
208
+ }
204
209
  export {};
@@ -1,4 +1,5 @@
1
1
  import { IHotelDetails } from '../../components/HotelResult/HotelResult.types';
2
+ import { ESearchType, ISearchLocation } from '../../services/hotel/HotelService.types';
2
3
  /**
3
4
  * @param searchResult - a search result from the hotel search
4
5
  * @returns Get Booking Options and TransferPartners for a single hotel searchResult
@@ -38,4 +39,27 @@ type ImageObject = {
38
39
  };
39
40
  type ImageData = ImageUrl | ImageObject;
40
41
  export declare function getHotelImageUrls(images?: ImageData[] | null): string[];
42
+ export declare const calculateStringSimilarity: (searchQuery: string, searchText: string) => number;
43
+ /**
44
+ * Sorts search results based on their relevance to the user query and predefined search types
45
+ * Used primarily for sorting location results in the autocomplete search
46
+ *
47
+ * @param {string} searchQuery - The text input provided by the user
48
+ * @param locationSearchResults - location results to be sorted
49
+ * @returns - sorted location results
50
+ */
51
+ export declare const sortLocationResults: (searchQuery: string, // text search input by user
52
+ similarityThreshold: number, searchSortOrder: Record<ESearchType, number>, locationSearchResults: ISearchLocation[]) => {
53
+ score: number;
54
+ startsWithText: string;
55
+ searchId: string;
56
+ searchType: ESearchType;
57
+ description: string;
58
+ coordinates: import('@type-op/shared').ICoordinates;
59
+ country: import('@type-op/shared').INameCode;
60
+ city: string;
61
+ state?: import('@type-op/shared').INameCode;
62
+ hotelChain?: string;
63
+ hotelName?: string;
64
+ }[];
41
65
  export {};
package/dist/main.js CHANGED
@@ -1,21 +1,24 @@
1
1
  import { ESearchType as r } from "./services/hotel/HotelService.types.js";
2
- import { HotelResult as p } from "./components/HotelResult/HotelResult.js";
3
- import { HotelResults as l } from "./components/HotelResults/HotelResults.js";
2
+ import { HotelResult as l } from "./components/HotelResult/HotelResult.js";
3
+ import { HotelResults as p } from "./components/HotelResults/HotelResults.js";
4
4
  import { Legend as x } from "./components/Legend/Legend.js";
5
- import { useHotelSearch as u } from "./hooks/useHotelSearch/useHotelSearch.js";
6
- import { useLocationSearch as S } from "./hooks/useLocationSearch/useLocationSearch.js";
7
- import { useHotelDetails as c } from "./hooks/useHotelDetails/useHotelDetails.js";
8
- import { useHotelSort as n } from "./hooks/useHotelSort/useHotelSort.js";
9
- import { EHotelSortOption as E, ESortingOrder as d } from "./enums/index.js";
5
+ import { useHotelSearch as s } from "./hooks/useHotelSearch/useHotelSearch.js";
6
+ import { useLocationSearch as u } from "./hooks/useLocationSearch/useLocationSearch.js";
7
+ import { useHotelDetails as d } from "./hooks/useHotelDetails/useHotelDetails.js";
8
+ import { useHotelSort as c } from "./hooks/useHotelSort/useHotelSort.js";
9
+ import { EHotelSortOption as n, ESortingOrder as E } from "./enums/index.js";
10
+ import { defaultLocationSortOrder as O, defaultSimilarityThreshold as g } from "./configs/defaults.js";
10
11
  export {
11
- E as EHotelSortOption,
12
+ n as EHotelSortOption,
12
13
  r as ESearchType,
13
- d as ESortingOrder,
14
- p as HotelResult,
15
- l as HotelResults,
14
+ E as ESortingOrder,
15
+ l as HotelResult,
16
+ p as HotelResults,
16
17
  x as Legend,
17
- c as useHotelDetails,
18
- u as useHotelSearch,
19
- n as useHotelSort,
20
- S as useLocationSearch
18
+ O as defaultLocationSortOrder,
19
+ g as defaultSimilarityThreshold,
20
+ d as useHotelDetails,
21
+ s as useHotelSearch,
22
+ c as useHotelSort,
23
+ u as useLocationSearch
21
24
  };
@@ -148,7 +148,9 @@ class w {
148
148
  n(this, "getRecommendations", async (s) => {
149
149
  try {
150
150
  const t = {
151
- hotels: (await new S(s.hotels).getConvertedHotels(s.userCurrency)).map((c) => ({
151
+ hotels: (await new S(s.hotels).getConvertedHotels(
152
+ s.userCurrency
153
+ )).map((c) => ({
152
154
  hotel_id: c.hotelId,
153
155
  hotel_group: c.hotelGroup,
154
156
  cash_value: c.cashValue,
@@ -1,26 +1,87 @@
1
- import { HotelChains as a } from "../../definitions/HotelChains.js";
2
- const s = (t) => {
3
- var r;
4
- const n = t.freeNight || t.nthNightFree !== 0 ? t.awardPoints : t.points, o = {
1
+ import { HotelChains as y } from "../../definitions/HotelChains.js";
2
+ var h = class f {
3
+ static initParams(t, r) {
4
+ return [t.replace(/\s+/g, "").toLowerCase(), r.replace(/\s+/g, "").toLowerCase()];
5
+ }
6
+ static checkThanosType(t) {
7
+ if (typeof t != "string") throw new Error("first argument should be a string");
8
+ }
9
+ static checkRivalType(t) {
10
+ if (typeof t != "string") throw new Error("second argument should be a string");
11
+ }
12
+ static checkAvengersType(t) {
13
+ if (!Array.isArray(t)) throw new Error("second argument should be an array of strings");
14
+ if (t.find((r) => typeof r != "string")) throw new Error("second argument should be an array of strings");
15
+ }
16
+ sortMatch(t, r) {
17
+ return f.checkThanosType(t), f.checkAvengersType(r), r.map((o, i) => ({ member: o, index: i, rating: this.similarity(t, o) })).sort((o, i) => o.rating - i.rating);
18
+ }
19
+ }, u = class extends h {
20
+ similarity(e, t) {
21
+ h.checkThanosType(e), h.checkRivalType(t);
22
+ let [r, o] = h.initParams(e, t), [i, c] = [r.length, o.length];
23
+ if (!r.length && !o.length || r === o) return 1;
24
+ if (i < 2 || c < 2) return 0;
25
+ let a = /* @__PURE__ */ new Map();
26
+ for (let n = 0; n < i - 1; n++) {
27
+ let s = r.slice(n, n + 2), p = a.has(s) ? a.get(s) + 1 : 1;
28
+ a.set(s, p);
29
+ }
30
+ let l = 0;
31
+ for (let n = 0; n < c - 1; n++) {
32
+ let s = o.slice(n, n + 2), p = a.has(s) ? a.get(s) : 0;
33
+ p > 0 && (a.set(s, p - 1), ++l);
34
+ }
35
+ return 2 * l / (i + c - 2);
36
+ }
37
+ distance(e, t) {
38
+ return 1 - this.similarity(e, t);
39
+ }
40
+ }, g = new u(), m = { diceCoefficient: g }, w = m;
41
+ const T = (e) => {
42
+ var c;
43
+ const t = e.freeNight || e.nthNightFree !== 0 ? e.awardPoints : e.points, r = {
5
44
  type: "",
6
45
  value: -1
7
- }, i = typeof t.cashValue.amount == "number" ? t.cashValue.amount : parseFloat(t.cashValue.amount), e = { ...o };
8
- return t.bestValue === "cash" ? (o.type = "cash", o.value = i, e.type = "points", e.value = n || -1) : t.bestValue === "points" && (o.type = "points", o.value = n || -1, e.type = "cash", e.value = i), {
9
- transferPartners: ((r = t.partners) == null ? void 0 : r.map((p) => ({
10
- ...p,
11
- value: n ? Math.ceil(n * p.ratio) : -1
46
+ }, o = typeof e.cashValue.amount == "number" ? e.cashValue.amount : parseFloat(e.cashValue.amount), i = { ...r };
47
+ return e.bestValue === "cash" ? (r.type = "cash", r.value = o, i.type = "points", i.value = t || -1) : e.bestValue === "points" && (r.type = "points", r.value = t || -1, i.type = "cash", i.value = o), {
48
+ transferPartners: ((c = e.partners) == null ? void 0 : c.map((a) => ({
49
+ ...a,
50
+ value: t ? Math.ceil(t * a.ratio) : -1
12
51
  }))) || [],
13
- bestBookingOption: o,
14
- alternateBookingOption: e,
15
- points: n || -1,
16
- hasPoints: typeof n == "number" && n > 0
52
+ bestBookingOption: r,
53
+ alternateBookingOption: i,
54
+ points: t || -1,
55
+ hasPoints: typeof t == "number" && t > 0
17
56
  };
18
- }, u = (t) => (t == null ? void 0 : t.hotelGroup) === a.IHG ? t.freeNight || t.nthNightFree ? t.awardPoints : t.points : t.awardPoints;
19
- function y(t) {
20
- return !t || !Array.isArray(t) || t.length === 0 ? [] : t.map((n) => typeof n == "string" ? n : n && typeof n == "object" && "url" in n ? n.url : "").filter((n) => n !== "");
57
+ }, b = (e) => (e == null ? void 0 : e.hotelGroup) === y.IHG ? e.freeNight || e.nthNightFree ? e.awardPoints : e.points : e.awardPoints;
58
+ function k(e) {
59
+ return !e || !Array.isArray(e) || e.length === 0 ? [] : e.map((t) => typeof t == "string" ? t : t && typeof t == "object" && "url" in t ? t.url : "").filter((t) => t !== "");
21
60
  }
61
+ const d = (e, t) => {
62
+ const r = e.toLowerCase().trim(), o = t.toLowerCase().trim();
63
+ return w.diceCoefficient.similarity(r, o) * 100;
64
+ }, C = (e, t, r, o) => {
65
+ const i = e.toLowerCase().trim(), c = o.map((n) => {
66
+ const s = n.description.toLowerCase().trim();
67
+ return {
68
+ ...n,
69
+ score: d(e, n.description),
70
+ startsWithText: s
71
+ };
72
+ }), a = c.filter(
73
+ (n) => n.startsWithText.startsWith(i) && n.score >= t
74
+ ), l = c.filter(
75
+ (n) => n.score < t
76
+ );
77
+ return a.sort((n, s) => s.score - n.score), l.sort(
78
+ (n, s) => r[n.searchType] - r[s.searchType]
79
+ ), [...a, ...l];
80
+ };
22
81
  export {
23
- s as getBookingOptions,
24
- y as getHotelImageUrls,
25
- u as getPointsValue
82
+ d as calculateStringSimilarity,
83
+ T as getBookingOptions,
84
+ k as getHotelImageUrls,
85
+ b as getPointsValue,
86
+ C as sortLocationResults
26
87
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@odynn/awayz-hotels",
3
3
  "private": false,
4
- "version": "0.2.19",
4
+ "version": "0.2.21",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -9,7 +9,7 @@
9
9
  "main": "dist/main.js",
10
10
  "types": "./dist/lib/main.d.ts",
11
11
  "scripts": {
12
- "test": "vite",
12
+ "test": "vitest",
13
13
  "dev": "npm run storybook",
14
14
  "build": "tsc -b ./tsconfig.lib.json && vite build",
15
15
  "stoot": "npm publish --access public",
@@ -66,6 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@odynn/awayz-core": "^0.2.22",
69
- "@tanstack/react-query": "^5.66.9"
69
+ "@tanstack/react-query": "^5.66.9",
70
+ "string-comparison": "^1.3.0"
70
71
  }
71
72
  }