@travories/frontend-sdk 0.1.1 → 0.1.3

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/dist/index.mjs CHANGED
@@ -214,15 +214,158 @@ var PackagesResource = class {
214
214
  }
215
215
  };
216
216
 
217
+ // src/api/agencies.ts
218
+ var normalizeImage2 = (img) => ({
219
+ id: img?.id ?? "",
220
+ key: img?.key ?? "",
221
+ type: img?.type ?? "image",
222
+ alt: img?.alt ?? "",
223
+ preview: img?.preview ?? null,
224
+ url: {
225
+ original: img?.url?.original ?? null,
226
+ hero: img?.url?.hero ?? null,
227
+ hero_fit: img?.url?.hero_fit ?? null,
228
+ section: img?.url?.section ?? null,
229
+ portrait: img?.url?.portrait ?? null,
230
+ general: img?.url?.general ?? null,
231
+ jpeg: img?.url?.jpeg ?? null
232
+ }
233
+ });
234
+ var normalizeAgencyCard = (raw) => ({
235
+ id: raw?.id ?? "",
236
+ title: raw?.title ?? "",
237
+ slug: raw?.slug ?? "",
238
+ agencySlug: raw?.agencySlug ?? "",
239
+ totalDays: Number(raw?.totalDays ?? 0),
240
+ minPrice: Number(raw?.minPrice ?? 0),
241
+ maxPrice: Number(raw?.maxPrice ?? 0),
242
+ rating: Number(raw?.rating ?? 0),
243
+ packageCategory: raw?.packageCategory ?? "",
244
+ thumbnail: normalizeImage2(raw?.thumbnail)
245
+ });
246
+ var AgenciesResource = class {
247
+ constructor(http) {
248
+ this.http = http;
249
+ }
250
+ /** Public profile of an agency by its slug. Null on 404. */
251
+ async getBySlug(slug, options) {
252
+ if (!slug) throw new Error("[TravoriesClient] agencies.getBySlug requires a slug");
253
+ const raw = await this.http.request(`/agency-info/by-slug/${slug}`, {
254
+ silent: true,
255
+ ...options
256
+ });
257
+ if (!raw?.hostDetails) return null;
258
+ return {
259
+ success: raw.success,
260
+ message: raw.message,
261
+ hostDetails: {
262
+ ...raw.hostDetails,
263
+ logo: raw.hostDetails.logo ? normalizeImage2(raw.hostDetails.logo) : null
264
+ }
265
+ };
266
+ }
267
+ /** Partner / association badges shown on the agency profile. */
268
+ async getAssociations(slug, options) {
269
+ if (!slug) throw new Error("[TravoriesClient] agencies.getAssociations requires a slug");
270
+ const raw = await this.http.request(
271
+ `/agency-association/agency/slug/${slug}`,
272
+ { silent: true, ...options }
273
+ );
274
+ if (!Array.isArray(raw)) return [];
275
+ return raw.map((a) => ({
276
+ id: a.id,
277
+ name: a.name,
278
+ url: a.url,
279
+ image: a.image ? normalizeImage2(a.image) : null
280
+ }));
281
+ }
282
+ /**
283
+ * Packages published by this agency. Returns the same card shape as the home
284
+ * sections so `<PackagesCarousel>` / `<PackageCard>` render them directly.
285
+ */
286
+ async getPackages(slug, params, options) {
287
+ if (!slug) throw new Error("[TravoriesClient] agencies.getPackages requires a slug");
288
+ const limit = params?.limit ?? 10;
289
+ const page = params?.page ?? 1;
290
+ const raw = await this.http.request(
291
+ `/agency-package/by-agency/${slug}?limit=${limit}&page=${page}`,
292
+ { silent: true, ...options }
293
+ );
294
+ if (!raw) return [];
295
+ const list = Array.isArray(raw) ? raw : Array.isArray(raw.packages) ? raw.packages : [];
296
+ return list.map(normalizeAgencyCard);
297
+ }
298
+ /**
299
+ * Convenience: fetch the full agency bundle (profile + associations + their
300
+ * packages) in parallel. Drives `<AgencyDetailView />`.
301
+ */
302
+ async getBundle(slug, params, options) {
303
+ const [agency, associations, packages] = await Promise.all([
304
+ this.getBySlug(slug, options),
305
+ this.getAssociations(slug, options),
306
+ this.getPackages(slug, { limit: params?.packagesLimit ?? 12 }, options)
307
+ ]);
308
+ if (!agency?.hostDetails) return null;
309
+ return {
310
+ agency: agency.hostDetails,
311
+ associations,
312
+ packages
313
+ };
314
+ }
315
+ };
316
+
317
+ // src/api/bookings.ts
318
+ var BookingsResource = class {
319
+ constructor(http) {
320
+ this.http = http;
321
+ }
322
+ /**
323
+ * Open a booking. The BE returns a booking UUID — combine it with
324
+ * `https://travories.com/package/<id>/payment`
325
+ * to send the user into the existing payment flow.
326
+ *
327
+ * Throws (not silent) so the consumer can surface errors to the user. Wrap
328
+ * in try/catch in your `onReserve` handler.
329
+ */
330
+ async initiate(payload, options) {
331
+ if (!payload?.packageId) {
332
+ throw new Error("[TravoriesClient] bookings.initiate requires packageId");
333
+ }
334
+ if (!payload?.arrivalDate) {
335
+ throw new Error("[TravoriesClient] bookings.initiate requires arrivalDate");
336
+ }
337
+ if (!payload?.travelers?.length) {
338
+ throw new Error("[TravoriesClient] bookings.initiate requires at least one traveler");
339
+ }
340
+ const res = await this.http.request(
341
+ `/booking/initiate`,
342
+ {
343
+ method: "POST",
344
+ body: payload,
345
+ silent: false,
346
+ ...options
347
+ }
348
+ );
349
+ if (!res?.data) {
350
+ throw new Error("[TravoriesClient] bookings.initiate returned no booking id");
351
+ }
352
+ return res;
353
+ }
354
+ };
355
+
217
356
  // src/client/TravoriesClient.ts
218
357
  var TravoriesClient = class {
219
358
  constructor(config) {
220
- /** Shortcut for `client.packages.getBySlug(slug)`. */
359
+ // ---- Convenience shortcuts on the client itself (no need to remember the
360
+ // resource name for the common one-shot lookups). -------------------
221
361
  this.getPackageBySlug = (slug) => this.packages.getBySlug(slug);
222
- /** Shortcut for `client.packages.getBundle(slug)` — package + host + attractions in one call. */
223
362
  this.getPackageBundle = (slug) => this.packages.getBundle(slug);
363
+ this.getAgencyBySlug = (slug) => this.agencies.getBySlug(slug);
364
+ this.getAgencyBundle = (slug) => this.agencies.getBundle(slug);
224
365
  this.http = new HttpClient(config);
225
366
  this.packages = new PackagesResource(this.http);
367
+ this.agencies = new AgenciesResource(this.http);
368
+ this.bookings = new BookingsResource(this.http);
226
369
  }
227
370
  };
228
371
  function createTravoriesClient(config) {
@@ -330,6 +473,40 @@ function useHomeSections(client) {
330
473
  }, [client]);
331
474
  return { data, loading, error, refetch: run };
332
475
  }
476
+ function useAgencyBundle(client, slug) {
477
+ const [data, setData] = useState(null);
478
+ const [loading, setLoading] = useState(Boolean(client && slug));
479
+ const [error, setError] = useState(null);
480
+ const reqId = useRef(0);
481
+ const run = () => {
482
+ if (!client || !slug) {
483
+ setData(null);
484
+ setLoading(false);
485
+ setError(null);
486
+ return;
487
+ }
488
+ const myReq = ++reqId.current;
489
+ setLoading(true);
490
+ setError(null);
491
+ client.agencies.getBundle(slug).then((res) => {
492
+ if (myReq !== reqId.current) return;
493
+ setData(res);
494
+ }).catch((err) => {
495
+ if (myReq !== reqId.current) return;
496
+ setError(err instanceof Error ? err : new Error(String(err)));
497
+ }).finally(() => {
498
+ if (myReq !== reqId.current) return;
499
+ setLoading(false);
500
+ });
501
+ };
502
+ useEffect(() => {
503
+ run();
504
+ return () => {
505
+ reqId.current++;
506
+ };
507
+ }, [client, slug]);
508
+ return { data, loading, error, refetch: run };
509
+ }
333
510
 
334
511
  // src/utils/format.ts
335
512
  function pickImageUrl(img) {
@@ -364,7 +541,7 @@ var PackageCard = ({
364
541
  onSelect,
365
542
  href,
366
543
  openInNewTab = false,
367
- showHeart = true,
544
+ showHeart = false,
368
545
  liked,
369
546
  onLike
370
547
  }) => {
@@ -818,16 +995,21 @@ var BookingCardLite = ({
818
995
  (o) => o.id === id ? { ...o, count: Math.max(0, o.count + (inc ? 1 : -1)) } : o
819
996
  )
820
997
  );
998
+ const [isSubmitting, setIsSubmitting] = useState(false);
821
999
  const handleReserve = () => {
822
1000
  if (!onReserve) return;
823
1001
  if (allPeopleCount === 0) return;
824
- onReserve({
1002
+ const result = onReserve({
825
1003
  arrival,
826
1004
  departure,
827
1005
  travelers: options.filter((o) => o.count > 0),
828
1006
  totalCost,
829
1007
  pricePerPerson: currentPrice
830
1008
  });
1009
+ if (result && typeof result.then === "function") {
1010
+ setIsSubmitting(true);
1011
+ result.finally(() => setIsSubmitting(false));
1012
+ }
831
1013
  };
832
1014
  return /* @__PURE__ */ jsxs("div", { className: "w-full sm:w-full lg:w-[520px] h-fit border rounded-xl shadow-md px-4 sm:px-6 bg-white flex flex-col gap-6 py-8 sm:py-10", children: [
833
1015
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
@@ -987,9 +1169,9 @@ var BookingCardLite = ({
987
1169
  {
988
1170
  type: "button",
989
1171
  onClick: handleReserve,
990
- disabled: allPeopleCount === 0 || !onReserve,
1172
+ disabled: allPeopleCount === 0 || !onReserve || isSubmitting,
991
1173
  className: "w-full py-2 md:py-3 bg-primary-normal text-white font-semibold rounded-lg hover:bg-primary-normal-hover transition text-sm md:text-base disabled:opacity-60 disabled:cursor-not-allowed",
992
- children: allPeopleCount === 0 ? "Reserve Now" : /* @__PURE__ */ jsxs(Fragment, { children: [
1174
+ children: isSubmitting ? "Initiating\u2026" : allPeopleCount === 0 ? "Reserve Now" : /* @__PURE__ */ jsxs(Fragment, { children: [
993
1175
  "Book Now - ",
994
1176
  formatCurrency(totalCost, currency)
995
1177
  ] })
@@ -1949,44 +2131,90 @@ var getMonthsHosting = (createdDate) => {
1949
2131
  );
1950
2132
  return Math.max(1, monthsDiff);
1951
2133
  };
1952
- var HostCard = ({ hostData, className = "" }) => {
1953
- const logoUrl = pickImageUrl(hostData?.logo);
1954
- return /* @__PURE__ */ jsxs(
1955
- "div",
1956
- {
1957
- className: `w-full sm:min-w-[320px] rounded-2xl border border-[#E0E4E8] bg-white flex flex-col gap-6 p-6 lg:p-8 shadow-md ${className}`,
1958
- children: [
1959
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
1960
- /* @__PURE__ */ jsx("div", { className: "relative rounded-full h-20 w-20 bg-gray-200 flex items-center justify-center text-xl text-primary-normal overflow-hidden", children: logoUrl ? /* @__PURE__ */ jsx(
1961
- "img",
1962
- {
1963
- src: logoUrl,
1964
- alt: `${hostData?.username}'s logo`,
1965
- className: "object-cover w-full h-full"
1966
- }
1967
- ) : /* @__PURE__ */ jsx("span", { children: getUserInitials(hostData?.username) }) }),
1968
- /* @__PURE__ */ jsx("span", { className: "text-[18px] tracking-[-0.02em] font-medium text-primary-normal whitespace-normal break-words", children: hostData?.username })
1969
- ] }),
1970
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-center mt-2", children: [
1971
- /* @__PURE__ */ jsxs("div", { children: [
1972
- /* @__PURE__ */ jsx("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: hostData?.review ?? 0 }),
1973
- /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Reviews" })
1974
- ] }),
1975
- /* @__PURE__ */ jsxs("div", { children: [
1976
- /* @__PURE__ */ jsx("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: (hostData?.rating ?? 0).toFixed(2) }),
1977
- /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Rating" })
1978
- ] }),
1979
- /* @__PURE__ */ jsxs("div", { children: [
1980
- /* @__PURE__ */ jsxs("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: [
1981
- getMonthsHosting(hostData?.agencyCreatedDate),
1982
- " mth"
1983
- ] }),
1984
- /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Hosting" })
1985
- ] })
1986
- ] })
1987
- ]
2134
+ var HostCard = ({
2135
+ hostData,
2136
+ onAgencyClick,
2137
+ href,
2138
+ openInNewTab,
2139
+ className = ""
2140
+ }) => {
2141
+ const data = hostData;
2142
+ const displayName = data.agencyName || data.username;
2143
+ const logoUrl = pickImageUrl(data?.logo);
2144
+ const isClickable = Boolean(onAgencyClick || href);
2145
+ const handleAnchorClick = (e) => {
2146
+ if (e.metaKey || e.ctrlKey || e.button === 1) return;
2147
+ if (openInNewTab) return;
2148
+ if (onAgencyClick) {
2149
+ e.preventDefault();
2150
+ onAgencyClick(data.slug);
1988
2151
  }
1989
- );
2152
+ };
2153
+ const body = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
2154
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
2155
+ /* @__PURE__ */ jsx("div", { className: "relative rounded-full h-20 w-20 bg-gray-200 flex items-center justify-center text-xl text-primary-normal overflow-hidden", children: logoUrl ? /* @__PURE__ */ jsx(
2156
+ "img",
2157
+ {
2158
+ src: logoUrl,
2159
+ alt: `${displayName}'s logo`,
2160
+ className: "object-cover w-full h-full"
2161
+ }
2162
+ ) : /* @__PURE__ */ jsx("span", { children: getUserInitials(displayName) }) }),
2163
+ /* @__PURE__ */ jsx("span", { className: "text-[18px] tracking-[-0.02em] font-medium text-primary-normal whitespace-normal break-words", children: displayName })
2164
+ ] }),
2165
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-center mt-2", children: [
2166
+ /* @__PURE__ */ jsxs("div", { children: [
2167
+ /* @__PURE__ */ jsx("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: data?.review ?? 0 }),
2168
+ /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Reviews" })
2169
+ ] }),
2170
+ /* @__PURE__ */ jsxs("div", { children: [
2171
+ /* @__PURE__ */ jsx("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: (data?.rating ?? 0).toFixed(2) }),
2172
+ /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Rating" })
2173
+ ] }),
2174
+ /* @__PURE__ */ jsxs("div", { children: [
2175
+ /* @__PURE__ */ jsxs("p", { className: "text-base md:text-lg text-primary-normal tracking-[-0.02em] font-medium", children: [
2176
+ getMonthsHosting(data?.agencyCreatedDate),
2177
+ " mth"
2178
+ ] }),
2179
+ /* @__PURE__ */ jsx("p", { className: "text-sm md:text-base text-secondary-normal-hover tracking-[-0.02em]", children: "Hosting" })
2180
+ ] })
2181
+ ] })
2182
+ ] });
2183
+ const wrapperClass = `w-full sm:min-w-[320px] rounded-2xl border border-[#E0E4E8] bg-white p-6 lg:p-8 shadow-md ${isClickable ? "cursor-pointer transition-shadow hover:shadow-lg" : ""} ${className}`.trim();
2184
+ if (href) {
2185
+ return /* @__PURE__ */ jsx(
2186
+ "a",
2187
+ {
2188
+ href,
2189
+ target: openInNewTab ? "_blank" : void 0,
2190
+ rel: openInNewTab ? "noopener noreferrer" : void 0,
2191
+ onClick: handleAnchorClick,
2192
+ className: `${wrapperClass} block no-underline text-inherit`,
2193
+ "aria-label": openInNewTab ? `View ${displayName} (opens in a new tab)` : `View ${displayName}`,
2194
+ children: body
2195
+ }
2196
+ );
2197
+ }
2198
+ if (onAgencyClick) {
2199
+ return /* @__PURE__ */ jsx(
2200
+ "div",
2201
+ {
2202
+ role: "button",
2203
+ tabIndex: 0,
2204
+ onClick: () => onAgencyClick(data.slug),
2205
+ onKeyDown: (e) => {
2206
+ if (e.key === "Enter" || e.key === " ") {
2207
+ e.preventDefault();
2208
+ onAgencyClick(data.slug);
2209
+ }
2210
+ },
2211
+ className: wrapperClass,
2212
+ "aria-label": `View ${displayName}`,
2213
+ children: body
2214
+ }
2215
+ );
2216
+ }
2217
+ return /* @__PURE__ */ jsx("div", { className: wrapperClass, children: body });
1990
2218
  };
1991
2219
  var HostCard_default = HostCard;
1992
2220
  var GalleryImg = ({
@@ -2276,6 +2504,9 @@ function PackageDetailView({
2276
2504
  initialBundle,
2277
2505
  currency = "USD",
2278
2506
  onReserve,
2507
+ onSelectHost,
2508
+ agencyHrefFor,
2509
+ openAgencyInNewTab,
2279
2510
  className,
2280
2511
  renderLoading,
2281
2512
  renderNotFound
@@ -2309,6 +2540,9 @@ function PackageDetailView({
2309
2540
  routes: bundle.routes ?? [],
2310
2541
  currency,
2311
2542
  onReserve,
2543
+ onSelectHost,
2544
+ agencyHrefFor,
2545
+ openAgencyInNewTab,
2312
2546
  className
2313
2547
  }
2314
2548
  );
@@ -2319,6 +2553,9 @@ function DetailContent({
2319
2553
  routes,
2320
2554
  currency,
2321
2555
  onReserve,
2556
+ onSelectHost,
2557
+ agencyHrefFor,
2558
+ openAgencyInNewTab,
2322
2559
  className
2323
2560
  }) {
2324
2561
  const topData = buildTopData(pkg, host);
@@ -2339,7 +2576,16 @@ function DetailContent({
2339
2576
  host && /* @__PURE__ */ jsxs("div", { className: "py-6 sm:py-8 border-b-2 border-gray-200 flex flex-col gap-6", children: [
2340
2577
  /* @__PURE__ */ jsx("h2", { className: "text-primary-normal text-xl md:text-2xl font-medium tracking-[-0.04em]", children: "Host Details" }),
2341
2578
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8 lg:gap-10 h-full items-start lg:items-center", children: [
2342
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6 sm:gap-8 w-full sm:w-[320px]", children: /* @__PURE__ */ jsx(HostCard_default, { hostData: host, className: "w-full" }) }),
2579
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6 sm:gap-8 w-full sm:w-[320px]", children: /* @__PURE__ */ jsx(
2580
+ HostCard_default,
2581
+ {
2582
+ hostData: host,
2583
+ onAgencyClick: onSelectHost ? () => onSelectHost(host) : void 0,
2584
+ href: agencyHrefFor ? agencyHrefFor(host) : void 0,
2585
+ openInNewTab: openAgencyInNewTab,
2586
+ className: "w-full"
2587
+ }
2588
+ ) }),
2343
2589
  /* @__PURE__ */ jsx("div", { className: "w-full lg:w-4/5 h-full flex flex-col justify-center", children: /* @__PURE__ */ jsx(
2344
2590
  HostAbout_default,
2345
2591
  {
@@ -2367,7 +2613,177 @@ function DefaultLoading() {
2367
2613
  ] })
2368
2614
  ] });
2369
2615
  }
2616
+ var AgencyAssociations = ({
2617
+ associations,
2618
+ title = "We are associated with",
2619
+ className
2620
+ }) => {
2621
+ if (!associations?.length) return null;
2622
+ return /* @__PURE__ */ jsxs("section", { className: `flex flex-col gap-4 mt-2 ${className ?? ""}`.trim(), children: [
2623
+ /* @__PURE__ */ jsx("h3", { className: "text-xl md:text-2xl font-medium tracking-[-0.04em] text-primary-normal", children: title }),
2624
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-6 items-center justify-start list-none p-0 m-0", children: associations.map((assoc) => {
2625
+ const img = pickImageUrl(assoc.image);
2626
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
2627
+ "a",
2628
+ {
2629
+ href: assoc.url,
2630
+ target: "_blank",
2631
+ rel: "noopener noreferrer",
2632
+ title: assoc.name,
2633
+ "aria-label": assoc.name,
2634
+ className: "relative w-32 h-20 flex items-center justify-center hover:opacity-80 transition-opacity rounded-lg p-2 bg-white border border-[#E0E4E8]",
2635
+ children: img ? /* @__PURE__ */ jsx(
2636
+ "img",
2637
+ {
2638
+ src: img,
2639
+ alt: assoc.image?.alt || assoc.name,
2640
+ loading: "lazy",
2641
+ className: "max-w-full max-h-full object-contain"
2642
+ }
2643
+ ) : /* @__PURE__ */ jsx("span", { className: "text-[#47586E] text-xs text-center leading-tight", children: assoc.name })
2644
+ }
2645
+ ) }, assoc.id);
2646
+ }) })
2647
+ ] });
2648
+ };
2649
+ var AgencyAssociations_default = AgencyAssociations;
2650
+ function AgencyDetailView({
2651
+ client,
2652
+ slug,
2653
+ initialBundle,
2654
+ currency = "USD",
2655
+ onSelectPackage,
2656
+ packageHrefFor,
2657
+ openPackagesInNewTab,
2658
+ className,
2659
+ renderLoading,
2660
+ renderNotFound
2661
+ }) {
2662
+ if (!initialBundle && (!client || !slug)) {
2663
+ throw new Error(
2664
+ "[AgencyDetailView] Provide either `initialBundle` or both `client` and `slug`."
2665
+ );
2666
+ }
2667
+ const remote = useAgencyBundle(
2668
+ initialBundle ? null : client ?? null,
2669
+ initialBundle ? null : slug ?? null
2670
+ );
2671
+ const bundle = initialBundle ?? remote.data;
2672
+ const loading = !initialBundle && remote.loading;
2673
+ const error = !initialBundle && remote.error;
2674
+ if (loading) {
2675
+ return /* @__PURE__ */ jsx("div", { className: `tvr-package-detail ${className ?? ""}`.trim(), children: renderLoading ? renderLoading() : /* @__PURE__ */ jsx(DefaultLoading2, {}) });
2676
+ }
2677
+ if (error) {
2678
+ return /* @__PURE__ */ jsx("div", { className: `tvr-package-detail ${className ?? ""}`.trim(), children: /* @__PURE__ */ jsxs("div", { className: "max-w-screen-xl mx-auto px-6 py-16 text-center text-red-600 text-sm", children: [
2679
+ "Failed to load agency: ",
2680
+ error.message
2681
+ ] }) });
2682
+ }
2683
+ if (!bundle?.agency) {
2684
+ return /* @__PURE__ */ jsx("div", { className: `tvr-package-detail ${className ?? ""}`.trim(), children: renderNotFound ? renderNotFound() : /* @__PURE__ */ jsx("div", { className: "max-w-screen-xl mx-auto px-6 py-16 text-center text-secondary-normal-hover text-sm", children: "Agency not found." }) });
2685
+ }
2686
+ return /* @__PURE__ */ jsx(
2687
+ DetailContent2,
2688
+ {
2689
+ agency: bundle.agency,
2690
+ associations: bundle.associations,
2691
+ packages: bundle.packages,
2692
+ currency,
2693
+ onSelectPackage,
2694
+ packageHrefFor,
2695
+ openPackagesInNewTab,
2696
+ className
2697
+ }
2698
+ );
2699
+ }
2700
+ function DetailContent2({
2701
+ agency,
2702
+ associations,
2703
+ packages,
2704
+ currency,
2705
+ onSelectPackage,
2706
+ packageHrefFor,
2707
+ openPackagesInNewTab,
2708
+ className
2709
+ }) {
2710
+ const displayName = agency.agencyName || agency.username;
2711
+ return /* @__PURE__ */ jsx("div", { className: `tvr-package-detail ${className ?? ""}`.trim(), children: /* @__PURE__ */ jsxs("article", { className: "mx-auto max-w-[1440px] flex flex-col gap-8 md:px-12 px-6 lg:py-10 py-6", children: [
2712
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-2", children: [
2713
+ /* @__PURE__ */ jsxs(
2714
+ "nav",
2715
+ {
2716
+ "aria-label": "Breadcrumb",
2717
+ className: "flex items-center gap-2 text-sm",
2718
+ children: [
2719
+ /* @__PURE__ */ jsx("a", { href: "/", className: "text-secondary hover:underline", children: "Home" }),
2720
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-secondary", children: "\u203A" }),
2721
+ /* @__PURE__ */ jsx("span", { className: "text-secondary underline font-medium", children: displayName })
2722
+ ]
2723
+ }
2724
+ ),
2725
+ /* @__PURE__ */ jsx("h1", { className: "text-xl md:text-2xl font-medium text-primary-normal leading-tight", children: displayName })
2726
+ ] }),
2727
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col lg:flex-row items-stretch gap-8 pb-8 border-b border-[#E0E4E8]", children: [
2728
+ /* @__PURE__ */ jsx("div", { className: "w-full lg:w-[320px] flex-shrink-0", children: /* @__PURE__ */ jsx(HostCard_default, { hostData: agency, className: "w-full" }) }),
2729
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-5 pt-2", children: [
2730
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2731
+ /* @__PURE__ */ jsx("h2", { className: "lg:text-2xl text-xl tracking-[-0.04em] font-medium text-primary-normal", children: "Overview" }),
2732
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-secondary font-medium md:text-lg text-sm", children: [
2733
+ /* @__PURE__ */ jsx(
2734
+ Icon,
2735
+ {
2736
+ icon: "material-symbols:verified-rounded",
2737
+ className: "lg:w-6 lg:h-6 w-4 h-4"
2738
+ }
2739
+ ),
2740
+ /* @__PURE__ */ jsx("span", { children: "Verified Agency" })
2741
+ ] })
2742
+ ] }),
2743
+ /* @__PURE__ */ jsx("p", { className: "lg:text-lg text-sm text-[#47586E] leading-relaxed", children: agency.description || `Verified Nepal travel agency on Travories.` })
2744
+ ] })
2745
+ ] }),
2746
+ associations.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2747
+ /* @__PURE__ */ jsx(AgencyAssociations_default, { associations }),
2748
+ /* @__PURE__ */ jsx("div", { className: "border-b border-[#E0E4E8]" })
2749
+ ] }),
2750
+ packages.length > 0 && /* @__PURE__ */ jsx("section", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsx(
2751
+ PackagesCarousel_default,
2752
+ {
2753
+ title: `Popular Packages from ${displayName}`,
2754
+ packages,
2755
+ currency,
2756
+ onSelect: onSelectPackage,
2757
+ hrefFor: packageHrefFor,
2758
+ openInNewTab: openPackagesInNewTab
2759
+ }
2760
+ ) })
2761
+ ] }) });
2762
+ }
2763
+ function DefaultLoading2() {
2764
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-[1440px] px-6 md:px-12 py-8 animate-pulse", children: [
2765
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-32 bg-gray-200 rounded mb-3" }),
2766
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-72 bg-gray-200 rounded mb-8" }),
2767
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col lg:flex-row gap-8 mb-10", children: [
2768
+ /* @__PURE__ */ jsx("div", { className: "w-full lg:w-[320px] h-48 bg-gray-100 rounded-2xl" }),
2769
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-3", children: [
2770
+ /* @__PURE__ */ jsx("div", { className: "h-6 w-40 bg-gray-200 rounded" }),
2771
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-full bg-gray-100 rounded" }),
2772
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-5/6 bg-gray-100 rounded" }),
2773
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-2/3 bg-gray-100 rounded" })
2774
+ ] })
2775
+ ] }),
2776
+ /* @__PURE__ */ jsx("div", { className: "flex gap-4 overflow-hidden", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx(
2777
+ "div",
2778
+ {
2779
+ className: "w-[300px] shrink-0 rounded-xl bg-gray-100",
2780
+ style: { height: 280 }
2781
+ },
2782
+ i
2783
+ )) })
2784
+ ] });
2785
+ }
2370
2786
 
2371
- export { BookingCardLite_default as BookingCardLite, DescriptionSection_default as DescriptionSection, GallerySection_default as GallerySection, HomeSections, HomeSectionsProvider, HostAbout_default as HostAbout, HostCard_default as HostCard, Itinerary_default as Itinerary, PackageCard_default as PackageCard, PackageDetailView, PackageExcludedAndToPack_default as PackageExcludedAndToPack, PackageIncluded_default as PackageIncluded, PackageMap, PackageOverview_default as PackageOverview, PackagesCarousel_default as PackagesCarousel, PackagesResource, PackagesSection_default as PackagesSection, TopSection_default as TopSection, TravoriesApiError, TravoriesClient, buildDescriptionData, buildGalleryMedia, buildTopData, createTravoriesClient, formatCurrency, formatRating, pickImageUrl, startingPrice, useHomeSections, useHomeSectionsContext, usePackageBundle, usePackageBySlug };
2787
+ export { AgenciesResource, AgencyAssociations_default as AgencyAssociations, AgencyDetailView, BookingCardLite_default as BookingCardLite, BookingsResource, DescriptionSection_default as DescriptionSection, GallerySection_default as GallerySection, HomeSections, HomeSectionsProvider, HostAbout_default as HostAbout, HostCard_default as HostCard, Itinerary_default as Itinerary, PackageCard_default as PackageCard, PackageDetailView, PackageExcludedAndToPack_default as PackageExcludedAndToPack, PackageIncluded_default as PackageIncluded, PackageMap, PackageOverview_default as PackageOverview, PackagesCarousel_default as PackagesCarousel, PackagesResource, PackagesSection_default as PackagesSection, TopSection_default as TopSection, TravoriesApiError, TravoriesClient, buildDescriptionData, buildGalleryMedia, buildTopData, createTravoriesClient, formatCurrency, formatRating, pickImageUrl, startingPrice, useAgencyBundle, useHomeSections, useHomeSectionsContext, usePackageBundle, usePackageBySlug };
2372
2788
  //# sourceMappingURL=index.mjs.map
2373
2789
  //# sourceMappingURL=index.mjs.map