@resira/ui 0.4.3 → 0.4.5

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.cjs CHANGED
@@ -652,6 +652,101 @@ function useCheckoutSession(token) {
652
652
  }, [client, token]);
653
653
  return { session, loading, error, errorCode };
654
654
  }
655
+ function formatPriceCentsUtil(cents, currency) {
656
+ return new Intl.NumberFormat("default", { style: "currency", currency }).format(cents / 100);
657
+ }
658
+ function formatDurationUtil(minutes) {
659
+ if (minutes < 60) return `${minutes} min`;
660
+ const h = Math.floor(minutes / 60);
661
+ const m = minutes % 60;
662
+ return m > 0 ? `${h}h ${m}m` : `${h}h`;
663
+ }
664
+ function enrichProduct(product) {
665
+ const currency = product.currency ?? "EUR";
666
+ const options = [];
667
+ if (product.durationPricing?.length) {
668
+ for (const dp of product.durationPricing) {
669
+ options.push({
670
+ durationMinutes: dp.durationMinutes,
671
+ durationLabel: formatDurationUtil(dp.durationMinutes),
672
+ priceCents: dp.priceCents,
673
+ priceFormatted: formatPriceCentsUtil(dp.priceCents, currency)
674
+ });
675
+ }
676
+ } else {
677
+ options.push({
678
+ durationMinutes: product.durationMinutes,
679
+ durationLabel: formatDurationUtil(product.durationMinutes),
680
+ priceCents: product.priceCents,
681
+ priceFormatted: formatPriceCentsUtil(product.priceCents, currency)
682
+ });
683
+ }
684
+ const lowestPriceCents = Math.min(...options.map((o) => o.priceCents));
685
+ return {
686
+ id: product.id,
687
+ name: product.name,
688
+ description: product.description,
689
+ imageUrl: product.imageUrl,
690
+ currency,
691
+ active: product.active,
692
+ pricingModel: product.pricingModel,
693
+ priceCents: product.priceCents,
694
+ priceFormatted: formatPriceCentsUtil(product.priceCents, currency),
695
+ lowestPriceCents,
696
+ lowestPriceFormatted: formatPriceCentsUtil(lowestPriceCents, currency),
697
+ hasMultipleOptions: options.length > 1,
698
+ durationMinutes: product.durationMinutes,
699
+ durationLabel: formatDurationUtil(product.durationMinutes),
700
+ options,
701
+ maxPartySize: product.maxPartySize,
702
+ equipmentIds: product.equipmentIds,
703
+ equipmentNames: product.equipmentNames,
704
+ serviceColor: product.serviceColor,
705
+ sortOrder: product.sortOrder,
706
+ raw: product
707
+ };
708
+ }
709
+ function useServices() {
710
+ const { client } = useResira();
711
+ const [services, setServices] = react.useState([]);
712
+ const [loading, setLoading] = react.useState(true);
713
+ const [error, setError] = react.useState(null);
714
+ const [fetchCount, setFetchCount] = react.useState(0);
715
+ react.useEffect(() => {
716
+ let cancelled = false;
717
+ setLoading(true);
718
+ setError(null);
719
+ async function load() {
720
+ try {
721
+ const data = await client.listProducts();
722
+ if (!cancelled) {
723
+ setServices((data.products ?? []).map(enrichProduct));
724
+ }
725
+ } catch (err) {
726
+ if (!cancelled) {
727
+ setError(err instanceof Error ? err.message : "Failed to load services");
728
+ }
729
+ } finally {
730
+ if (!cancelled) setLoading(false);
731
+ }
732
+ }
733
+ load();
734
+ return () => {
735
+ cancelled = true;
736
+ };
737
+ }, [client, fetchCount]);
738
+ const refetch = react.useCallback(() => setFetchCount((c) => c + 1), []);
739
+ return { services, loading, error, refetch };
740
+ }
741
+ async function fetchServices(apiKey, opts) {
742
+ const { Resira: Resira2 } = await import('@resira/sdk');
743
+ const client = new Resira2({
744
+ apiKey,
745
+ ...opts?.baseUrl ? { baseUrl: opts.baseUrl } : {}
746
+ });
747
+ const data = await client.listProducts();
748
+ return (data.products ?? []).map(enrichProduct);
749
+ }
655
750
  var defaultSize = 20;
656
751
  function CalendarIcon({ size = defaultSize, className }) {
657
752
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -4260,6 +4355,7 @@ exports.UsersIcon = UsersIcon;
4260
4355
  exports.ViewfinderIcon = ViewfinderIcon;
4261
4356
  exports.WaiverConsent = WaiverConsent;
4262
4357
  exports.XIcon = XIcon;
4358
+ exports.fetchServices = fetchServices;
4263
4359
  exports.resolveTheme = resolveTheme;
4264
4360
  exports.themeToCSS = themeToCSS;
4265
4361
  exports.useAvailability = useAvailability;
@@ -4271,6 +4367,7 @@ exports.useProducts = useProducts;
4271
4367
  exports.useReservation = useReservation;
4272
4368
  exports.useResira = useResira;
4273
4369
  exports.useResources = useResources;
4370
+ exports.useServices = useServices;
4274
4371
  exports.validateGuestForm = validateGuestForm;
4275
4372
  //# sourceMappingURL=index.cjs.map
4276
4373
  //# sourceMappingURL=index.cjs.map