@cimplify/sdk 0.73.0 → 0.74.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/dist/react.d.mts +36 -2
- package/dist/react.d.ts +36 -2
- package/dist/react.js +187 -66
- package/dist/react.mjs +187 -67
- package/package.json +1 -1
- package/registry/product-customizer.json +1 -1
package/dist/react.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import { d as AdSlot, c as AdPosition, a as AdContextValue, S as SignInOptions }
|
|
|
3
3
|
export { A as AdConfig, g as getVariantDisplayName } from './sign-in-DQlIdqsi.mjs';
|
|
4
4
|
import { ad as CimplifyClient, cj as ProcessCheckoutResult, aa as CheckoutStatus, ab as CheckoutStatusContext, aV as EnrichedOrderItem, aU as EnrichedOrder, w as Business, bp as Location, cA as ReorderResult, b$ as OrderStatus, bF as Order, cl as QuoteBundleSelectionInput, cm as QuoteCompositeSelectionInput, cf as PriceQuote, cp as QuoteUiMessage, cV as Service, r as AvailableSlot, av as DayAvailability, an as CustomerBooking, M as CancelBookingResult, f as ActivityStateResponse, d2 as SessionMessage, c as ActivityRecommendation, ax as DeliveryFeeResponse, b6 as FxRateResponse, db as StorefrontBootstrap, Y as ChatWidgetStarter, X as ChatMessage, h as AddressInfo, n as AuthenticatedData, aT as ElementsOptions, c9 as PaymentMethodInfo, aR as ElementsCheckoutResult, ci as ProcessCheckoutOptions, ag as CimplifyElements, bg as LineItem, d5 as Staff, cQ as Room } from './client-C7EMuGoz.mjs';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
-
import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.mjs';
|
|
6
|
+
import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, aj as DepositType, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.mjs';
|
|
7
7
|
import { P as ProductWithPrice } from './price-Cm0tU0V5.mjs';
|
|
8
8
|
import { ClassValue } from 'clsx';
|
|
9
9
|
import { Matcher } from 'react-day-picker';
|
|
@@ -2632,6 +2632,40 @@ interface StaffPickerProps {
|
|
|
2632
2632
|
}
|
|
2633
2633
|
declare function StaffPicker({ staff, selectedStaffId, onStaffSelect, showAnyOption, anyLabel, className, classNames, }: StaffPickerProps): React$1.ReactElement;
|
|
2634
2634
|
|
|
2635
|
+
interface BookingSummaryClassNames {
|
|
2636
|
+
root?: string;
|
|
2637
|
+
header?: string;
|
|
2638
|
+
row?: string;
|
|
2639
|
+
label?: string;
|
|
2640
|
+
value?: string;
|
|
2641
|
+
totals?: string;
|
|
2642
|
+
deposit?: string;
|
|
2643
|
+
balance?: string;
|
|
2644
|
+
}
|
|
2645
|
+
interface BookingSummaryProps {
|
|
2646
|
+
/** The chosen slot — provides the date and time. */
|
|
2647
|
+
slot: AvailableSlot;
|
|
2648
|
+
/** Resolved per-booking total (variant/add-ons included), pre-deposit. */
|
|
2649
|
+
total: number;
|
|
2650
|
+
/** Selected staff member's name, when one was chosen. */
|
|
2651
|
+
staffName?: string | null;
|
|
2652
|
+
/** Service duration, shown in the header. */
|
|
2653
|
+
durationMinutes?: number;
|
|
2654
|
+
/** Deposit policy — drives the "due now" / "balance" split. */
|
|
2655
|
+
depositType?: DepositType;
|
|
2656
|
+
depositAmount?: Money;
|
|
2657
|
+
currency?: CurrencyCode;
|
|
2658
|
+
className?: string;
|
|
2659
|
+
classNames?: BookingSummaryClassNames;
|
|
2660
|
+
}
|
|
2661
|
+
/**
|
|
2662
|
+
* BookingSummary — a live recap of a service booking: who, when, and the
|
|
2663
|
+
* deposit-due / balance split derived from the product's deposit policy.
|
|
2664
|
+
*
|
|
2665
|
+
* Presentational: the host owns the selected slot, staff and quote total.
|
|
2666
|
+
*/
|
|
2667
|
+
declare function BookingSummary({ slot, total, staffName, durationMinutes, depositType, depositAmount, currency, className, classNames, }: BookingSummaryProps): React$1.ReactElement;
|
|
2668
|
+
|
|
2635
2669
|
interface BookingCardClassNames {
|
|
2636
2670
|
root?: string;
|
|
2637
2671
|
service?: string;
|
|
@@ -3662,4 +3696,4 @@ interface ChatWidgetProps {
|
|
|
3662
3696
|
}
|
|
3663
3697
|
declare function ChatWidget({ client: clientProp, businessName, greeting, subtitle, starters, placeholder, position, defaultOpen, pollInterval, className, classNames, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
|
|
3664
3698
|
|
|
3665
|
-
export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
|
3699
|
+
export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingSummary, type BookingSummaryClassNames, type BookingSummaryProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
package/dist/react.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { d as AdSlot, c as AdPosition, a as AdContextValue, S as SignInOptions }
|
|
|
3
3
|
export { A as AdConfig, g as getVariantDisplayName } from './sign-in-DQlIdqsi.js';
|
|
4
4
|
import { ad as CimplifyClient, cj as ProcessCheckoutResult, aa as CheckoutStatus, ab as CheckoutStatusContext, aV as EnrichedOrderItem, aU as EnrichedOrder, w as Business, bp as Location, cA as ReorderResult, b$ as OrderStatus, bF as Order, cl as QuoteBundleSelectionInput, cm as QuoteCompositeSelectionInput, cf as PriceQuote, cp as QuoteUiMessage, cV as Service, r as AvailableSlot, av as DayAvailability, an as CustomerBooking, M as CancelBookingResult, f as ActivityStateResponse, d2 as SessionMessage, c as ActivityRecommendation, ax as DeliveryFeeResponse, b6 as FxRateResponse, db as StorefrontBootstrap, Y as ChatWidgetStarter, X as ChatMessage, h as AddressInfo, n as AuthenticatedData, aT as ElementsOptions, c9 as PaymentMethodInfo, aR as ElementsCheckoutResult, ci as ProcessCheckoutOptions, ag as CimplifyElements, bg as LineItem, d5 as Staff, cQ as Room } from './client-D6CZ2Ggp.js';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
-
import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.js';
|
|
6
|
+
import { ab as CurrencyCode, aX as Product, aO as Pagination, T as CimplifyError, b9 as ProductWithDetails, Q as Category, aM as Money, C as BundleSelectionInput, $ as ComponentSelectionInput, z as BundleSelectionData, a8 as CompositeSelectionData, U as Collection, b4 as ProductTaxonomy, bt as TaxonomyWithChildren, b5 as ProductTimeProfile, ah as Deal, b0 as ProductDealInfo, an as DiscountValidation, E as BundleSummary, a6 as CompositePriceResult, bo as SubscriptionWithDetails, bn as SubscriptionStatus, bk as Subscription, ac as CustomAttributeDefinition, ba as PropertyFacet, a$ as ProductBillingPlan, bL as VariantView, bF as VariantAxisWithValues, f as AddOnWithOptions, w as BundleComponentView, x as BundlePriceType, a4 as CompositeGroupView, aq as DisplayCart, b1 as ProductInputField, bg as SchedulingMode, at as DurationUnit, aj as DepositType, ad as CustomAttributeValue, b2 as ProductProperty, bc as QuantityPricingTier } from './product-B_kS4Oxa.js';
|
|
7
7
|
import { P as ProductWithPrice } from './price-9T1Y47oS.js';
|
|
8
8
|
import { ClassValue } from 'clsx';
|
|
9
9
|
import { Matcher } from 'react-day-picker';
|
|
@@ -2632,6 +2632,40 @@ interface StaffPickerProps {
|
|
|
2632
2632
|
}
|
|
2633
2633
|
declare function StaffPicker({ staff, selectedStaffId, onStaffSelect, showAnyOption, anyLabel, className, classNames, }: StaffPickerProps): React$1.ReactElement;
|
|
2634
2634
|
|
|
2635
|
+
interface BookingSummaryClassNames {
|
|
2636
|
+
root?: string;
|
|
2637
|
+
header?: string;
|
|
2638
|
+
row?: string;
|
|
2639
|
+
label?: string;
|
|
2640
|
+
value?: string;
|
|
2641
|
+
totals?: string;
|
|
2642
|
+
deposit?: string;
|
|
2643
|
+
balance?: string;
|
|
2644
|
+
}
|
|
2645
|
+
interface BookingSummaryProps {
|
|
2646
|
+
/** The chosen slot — provides the date and time. */
|
|
2647
|
+
slot: AvailableSlot;
|
|
2648
|
+
/** Resolved per-booking total (variant/add-ons included), pre-deposit. */
|
|
2649
|
+
total: number;
|
|
2650
|
+
/** Selected staff member's name, when one was chosen. */
|
|
2651
|
+
staffName?: string | null;
|
|
2652
|
+
/** Service duration, shown in the header. */
|
|
2653
|
+
durationMinutes?: number;
|
|
2654
|
+
/** Deposit policy — drives the "due now" / "balance" split. */
|
|
2655
|
+
depositType?: DepositType;
|
|
2656
|
+
depositAmount?: Money;
|
|
2657
|
+
currency?: CurrencyCode;
|
|
2658
|
+
className?: string;
|
|
2659
|
+
classNames?: BookingSummaryClassNames;
|
|
2660
|
+
}
|
|
2661
|
+
/**
|
|
2662
|
+
* BookingSummary — a live recap of a service booking: who, when, and the
|
|
2663
|
+
* deposit-due / balance split derived from the product's deposit policy.
|
|
2664
|
+
*
|
|
2665
|
+
* Presentational: the host owns the selected slot, staff and quote total.
|
|
2666
|
+
*/
|
|
2667
|
+
declare function BookingSummary({ slot, total, staffName, durationMinutes, depositType, depositAmount, currency, className, classNames, }: BookingSummaryProps): React$1.ReactElement;
|
|
2668
|
+
|
|
2635
2669
|
interface BookingCardClassNames {
|
|
2636
2670
|
root?: string;
|
|
2637
2671
|
service?: string;
|
|
@@ -3662,4 +3696,4 @@ interface ChatWidgetProps {
|
|
|
3662
3696
|
}
|
|
3663
3697
|
declare function ChatWidget({ client: clientProp, businessName, greeting, subtitle, starters, placeholder, position, defaultOpen, pollInterval, className, classNames, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
|
|
3664
3698
|
|
|
3665
|
-
export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
|
3699
|
+
export { AccommodationCard, AccountContent, type AccountContentProps, AccountDashboardPage, type AccountDashboardPageProps, AccountHero, type AccountHeroProps, AccountIdentityStrip, type AccountIdentityStripProps, AccountLineItem, type AccountLineItemData, type AccountLineItemProps, AccountLineItems, type AccountLineItemsProps, AccountNav, type AccountNavProps, AccountOrderDetailPage, type AccountOrderDetailPageProps, AccountOrderView, type AccountOrderViewProps, AccountOrdersPage, type AccountOrdersPageProps, type AccountPageBaseProps, AccountShell, type AccountShellProps, AccountSidebar, type AccountSidebarProps, AccountSignedOutPrompt, type AccountSignedOutPromptProps, AccountSubscriptionDetailPage, type AccountSubscriptionDetailPageProps, AccountSubscriptionsPage, type AccountSubscriptionsPageProps, Ad, AdPosition, type AdProps, AdProvider, AdSlot, AddOnSelector, type AddOnSelectorClassNames, type AddOnSelectorProps, type AddToCartOptions, AddressElement, AuthElement, AvailabilityBadge, type AvailabilityBadgeClassNames, type AvailabilityBadgeProps, BackLink, type BackLinkProps, BillingPlanSelector, type BillingPlanSelectorClassNames, type BillingPlanSelectorProps, BookingCard, type BookingCardClassNames, type BookingCardProps, BookingList, type BookingListClassNames, type BookingListProps, BookingPage, type BookingPageClassNames, type BookingPageProps, BookingSummary, type BookingSummaryClassNames, type BookingSummaryProps, BookingsPage, type BookingsPageClassNames, type BookingsPageProps, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, type BundleSelectorClassNames, type BundleSelectorProps, Button, type ButtonProps, CardImage, type CardLayoutProps, CardShell, CardVariant, type CartAddOnOptionSelection, CartDrawer, type CartDrawerProps, CartDrawerProvider, type CartLayoutProps, CartPage, type CartPageClassNames, type CartPageProps, CartSummary, type CartSummaryClassNames, type CartSummaryProps, CartTemplate, type CartVariantSelection, CatalogueCollectionLayout, type CatalogueLayoutProps, CataloguePage, type CataloguePageClassNames, type CataloguePageProps, CatalogueTemplate, CategoryFilter, type CategoryFilterClassNames, type CategoryFilterProps, CategoryGrid, type CategoryGridClassNames, type CategoryGridProps, ChatWidget, type ChatWidgetClassNames, type ChatWidgetProps, CheckIcon, CheckoutPage, type CheckoutPageClassNames, type CheckoutPageProps, CimplifyCheckout, type CimplifyCheckoutProps, type CimplifyClientContextValue, type CimplifyClientSession, type CimplifyContextValue, CimplifyProvider, type CimplifyProviderProps, CimplifySignInButton, type CimplifySignInButtonProps, CimplifyUserButton, type CimplifyUserButtonProps, type CollectionLayoutProps, CollectionPage, type CollectionPageClassNames, type CollectionPageProps, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, type CompositeSelectorClassNames, type CompositeSelectorProps, ContextCard, type ContextCardProps, type ContextRow, ContinuityCard, type ContinuityCardProps, CurrencySelector, type CurrencySelectorClassNames, type CurrencySelectorProps, CustomAttributesTable, type CustomerInput, CustomerInputFields, type CustomerInputFieldsClassNames, type CustomerInputFieldsProps, type CustomerInputType, DashboardIcon, DashboardIcon20, DatePicker, type DatePickerClassNames, type DatePickerProps, DateSlotPicker, type DateSlotPickerClassNames, type DateSlotPickerProps, DealBanner, type DealBannerClassNames, type DealBannerProps, DealsPage, type DealsPageClassNames, type DealsPageProps, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, type DeliveryEstimateClassNames, type DeliveryEstimateProps, type DeliveryLive, type DeliveryRider, DeliveryTracker, type DeliveryTrackerProps, DeliveryTruckIcon, type DigitalFulfillment, DigitalProductCard, DigitalProductLayout, DiscountInput, type DiscountInputClassNames, type DiscountInputProps, ElementsProvider, EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, FeaturedCollectionLayout, type FilterTabItem, FilterTabs, type FilterTabsProps, FoodProductCard, FoodProductLayout, HappeningCard, type HappeningCardProps, type HappeningPaneData, IdentityIcon, IdentityOfframp, type IdentityOfframpProps, type IdentitySummary, InventoryBadge, ItemsCard, type ItemsCardProps, LeaseServiceCard, LineItemDetails, type LineItemSemanticKind, type LineScheduling, type LineSelection, type LineStateTone, LocationPicker, type LocationPickerClassNames, type LocationPickerProps, MediaGallery, type MediaGalleryProps, type MediaItem, MetadataStringList, MobileAccountShell, type MobileAccountShellProps, MobileBackButton, MobileMoreButton, MobileTabBar, type MobileTabBarProps, type NavItem, NextDeliveryCard, type NextDeliveryCardProps, OrderDetailHeader, type OrderDetailHeaderProps, OrderDetailMetaPipe, OrderDetailPage, type OrderDetailPageClassNames, type OrderDetailPageProps, OrderHistory, type OrderHistoryClassNames, OrderHistoryPage, type OrderHistoryPageClassNames, type OrderHistoryPageProps, type OrderHistoryProps, type OrderItemData, OrderList, type OrderListProps, OrderRow, type OrderRowData, type OrderRowProps, type OrderRowStatus, type OrderStatusTone, OrderSummary, type OrderSummaryClassNames, type OrderSummaryProps, OrderTimeline, type OrderTimelineProps, OrderTotals, type OrderTotalsProps, type OrderViewDelivery, type OrderViewPayment, type OrderViewPaymentRow, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, type PriceProps, PriceRange, type PriceRangeProps, ProductCard, type ProductCardClassNames, type ProductCardProps, ProductCustomizer, type ProductCustomizerClassNames, type ProductCustomizerProps, ProductGrid, type ProductGridClassNames, type ProductGridProps, ProductImageGallery, type ProductImageGalleryProps, type ProductLayoutProps, ProductModel3D, type ProductModel3DProps, ProductPage, type ProductPageClassNames, type ProductPageProps, ProductSheet, type ProductSheetClassNames, type ProductSheetProps, ProductTemplate, PropertiesTable, QuantitySelector, type QuantitySelectorClassNames, type QuantitySelectorProps, QuickAddButton, RecentlyViewed, type RecentlyViewedClassNames, type RecentlyViewedProps, RecommendationCarousel, type RecommendationCarouselClassNames, type RecommendationCarouselProps, RelatedProductsSection, RentalServiceCard, type Resource, ResourcePicker, type ResourcePickerClassNames, type ResourcePickerProps, RetailProductCard, RichText, type RichTextProps, SaleBadge, type SaleBadgeClassNames, type SaleBadgeProps, ScheduleServiceCard, SearchInput, type SearchInputClassNames, type SearchInputProps, type SearchLayoutProps, SearchPage, type SearchPageClassNames, type SearchPageProps, SearchTemplate, Section, SectionMore, type SectionMoreProps, type SectionProps, type ServiceCardLayoutProps, ServiceProductLayout, SessionMessageBanner, type SessionMessageBannerClassNames, type SessionMessageBannerProps, SignOutIcon, Skeleton, type SkeletonProps, SlotPicker, type SlotPickerClassNames, type SlotPickerProps, SoldOutOverlay, StaffPicker, type StaffPickerClassNames, type StaffPickerProps, StandardServiceCard, Status, type StatusProps, StoreNav, type StoreNavClassNames, type StoreNavProps, StoreVideo, type StoreVideoProps, SubscriptionCard, SubscriptionList, type SubscriptionListProps, SubscriptionRow, type SubscriptionRowData, type SubscriptionRowProps, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, type TimePickerClassNames, type TimePickerProps, type TimelineStep, type ToAccountOrderViewOptions, Toast, type ToastProps, type TotalsData, TwoColumnGrid, type UseActivityStateOptions, type UseActivityStateResult, type UseAttributeDefinitionsOptions, type UseAttributeDefinitionsResult, type UseAvailableSlotsOptions, type UseAvailableSlotsResult, type UseBillingPlansOptions, type UseBillingPlansResult, type UseBookingsOptions, type UseBookingsResult, type UseBootstrapOptions, type UseBootstrapResult, type UseBundlesOptions, type UseBundlesResult, type UseCartItem, type UseCartOptions, type UseCartResult, type UseCategoriesOptions, type UseCategoriesResult, type UseChatOptions, type UseChatResult, type UseCimplifySessionOptions, type UseCimplifySessionResult, type UseCollectionOptions, type UseCollectionResult, type UseCollectionsOptions, type UseCollectionsResult, type UseDealsOptions, type UseDealsResult, type UseDeliveryFeeOptions, type UseDeliveryFeeResult, type UseFxRateOptions, type UseFxRateResult, type UseLocationsOptions, type UseLocationsResult, type UseOrderOptions, type UseOrderResult, type UseOrdersOptions, type UseOrdersResult, type UseProductAvailabilityOptions, type UseProductAvailabilityResult, type UseProductDealsOptions, type UseProductDealsResult, type UseProductOptions, type UseProductPriceInput, type UseProductPriceResult, type UseProductResult, type UseProductSchedulesOptions, type UseProductSchedulesResult, type UseProductsOnSaleOptions, type UseProductsOnSaleResult, type UseProductsOptions, type UseProductsResult, type UsePropertyFacetsOptions, type UsePropertyFacetsResult, type UseQuoteInput, type UseQuoteOptions, type UseQuoteResult, type UseRecommendationsOptions, type UseRecommendationsResult, type UseSearchOptions, type UseSearchResult, type UseServiceAvailabilityOptions, type UseServiceAvailabilityResult, type UseServicesOptions, type UseServicesResult, type UseTaxonomiesOptions, type UseTaxonomiesResult, type UseTaxonomyOptions, type UseTaxonomyPathOptions, type UseTaxonomyPathResult, type UseTaxonomyResult, type UseValidateDiscountOptions, type UseValidateDiscountResult, type UseVariantSelectorOptions, type UseVariantSelectorResult, type UserButtonLink, VariantSelector, type VariantSelectorClassNames, type VariantSelectorProps, VolumePricing, type VolumePricingClassNames, type VolumePricingProps, WelcomeCard, type WelcomeCardProps, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
package/dist/react.js
CHANGED
|
@@ -7311,6 +7311,144 @@ function formatDuration2(value, unit) {
|
|
|
7311
7311
|
const label = value === 1 ? labels.singular : labels.plural;
|
|
7312
7312
|
return `${value} ${label}`;
|
|
7313
7313
|
}
|
|
7314
|
+
var ANY_VALUE = "__any__";
|
|
7315
|
+
function StaffPicker({
|
|
7316
|
+
staff,
|
|
7317
|
+
selectedStaffId,
|
|
7318
|
+
onStaffSelect,
|
|
7319
|
+
showAnyOption = true,
|
|
7320
|
+
anyLabel = "Any available",
|
|
7321
|
+
className,
|
|
7322
|
+
classNames
|
|
7323
|
+
}) {
|
|
7324
|
+
const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
|
|
7325
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7326
|
+
radioGroup.RadioGroup,
|
|
7327
|
+
{
|
|
7328
|
+
"data-cimplify-staff-picker": true,
|
|
7329
|
+
className: cn(className, classNames?.root),
|
|
7330
|
+
value: groupValue,
|
|
7331
|
+
onValueChange: (value) => {
|
|
7332
|
+
onStaffSelect?.(value === ANY_VALUE ? null : value);
|
|
7333
|
+
},
|
|
7334
|
+
children: [
|
|
7335
|
+
showAnyOption && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7336
|
+
radio.Radio.Root,
|
|
7337
|
+
{
|
|
7338
|
+
value: ANY_VALUE,
|
|
7339
|
+
"data-cimplify-staff-option": true,
|
|
7340
|
+
"data-selected": selectedStaffId === null || void 0,
|
|
7341
|
+
"data-any": true,
|
|
7342
|
+
className: classNames?.option,
|
|
7343
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
|
|
7344
|
+
}
|
|
7345
|
+
),
|
|
7346
|
+
staff.map((member) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7347
|
+
radio.Radio.Root,
|
|
7348
|
+
{
|
|
7349
|
+
value: member.id,
|
|
7350
|
+
"data-cimplify-staff-option": true,
|
|
7351
|
+
"data-selected": selectedStaffId === member.id || void 0,
|
|
7352
|
+
className: classNames?.option,
|
|
7353
|
+
children: [
|
|
7354
|
+
member.avatar_url && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7355
|
+
"img",
|
|
7356
|
+
{
|
|
7357
|
+
src: member.avatar_url,
|
|
7358
|
+
alt: member.name,
|
|
7359
|
+
"data-cimplify-staff-avatar": true,
|
|
7360
|
+
className: classNames?.avatar
|
|
7361
|
+
}
|
|
7362
|
+
),
|
|
7363
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
|
|
7364
|
+
member.bio && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
|
|
7365
|
+
]
|
|
7366
|
+
},
|
|
7367
|
+
member.id
|
|
7368
|
+
))
|
|
7369
|
+
]
|
|
7370
|
+
}
|
|
7371
|
+
);
|
|
7372
|
+
}
|
|
7373
|
+
function formatDate(value) {
|
|
7374
|
+
const date = new Date(value);
|
|
7375
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
7376
|
+
return date.toLocaleDateString(void 0, {
|
|
7377
|
+
weekday: "short",
|
|
7378
|
+
month: "short",
|
|
7379
|
+
day: "numeric"
|
|
7380
|
+
});
|
|
7381
|
+
}
|
|
7382
|
+
function formatTime(value) {
|
|
7383
|
+
const date = new Date(value);
|
|
7384
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
7385
|
+
return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
7386
|
+
}
|
|
7387
|
+
function BookingSummary({
|
|
7388
|
+
slot,
|
|
7389
|
+
total,
|
|
7390
|
+
staffName,
|
|
7391
|
+
durationMinutes,
|
|
7392
|
+
depositType,
|
|
7393
|
+
depositAmount,
|
|
7394
|
+
currency,
|
|
7395
|
+
className,
|
|
7396
|
+
classNames
|
|
7397
|
+
}) {
|
|
7398
|
+
const depositValue = depositAmount != null ? chunk7Y2O3E4D_js.parsePrice(depositAmount) : 0;
|
|
7399
|
+
const depositDue = depositType === "percentage" ? total * depositValue / 100 : depositType === "fixed" ? depositValue : 0;
|
|
7400
|
+
const hasDeposit = depositDue > 0;
|
|
7401
|
+
const balance = Math.max(0, total - depositDue);
|
|
7402
|
+
const rowClass = cn("flex items-center justify-between", classNames?.row);
|
|
7403
|
+
const labelClass = cn("text-muted-foreground", classNames?.label);
|
|
7404
|
+
const valueClass = cn("font-medium", classNames?.value);
|
|
7405
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7406
|
+
"div",
|
|
7407
|
+
{
|
|
7408
|
+
"data-cimplify-booking-summary": true,
|
|
7409
|
+
className: cn("rounded-lg border border-border p-4 space-y-3", className, classNames?.root),
|
|
7410
|
+
children: [
|
|
7411
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between", classNames?.header), children: [
|
|
7412
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold", children: "Your booking" }),
|
|
7413
|
+
durationMinutes != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
7414
|
+
durationMinutes,
|
|
7415
|
+
" min"
|
|
7416
|
+
] })
|
|
7417
|
+
] }),
|
|
7418
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 text-sm", children: [
|
|
7419
|
+
staffName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
|
|
7420
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "With" }),
|
|
7421
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: staffName })
|
|
7422
|
+
] }),
|
|
7423
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
|
|
7424
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Date" }),
|
|
7425
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: formatDate(slot.start_time) })
|
|
7426
|
+
] }),
|
|
7427
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
|
|
7428
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Time" }),
|
|
7429
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: valueClass, children: formatTime(slot.start_time) })
|
|
7430
|
+
] })
|
|
7431
|
+
] }),
|
|
7432
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("border-t border-border pt-3 space-y-1.5 text-sm", classNames?.totals), children: [
|
|
7433
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: rowClass, children: [
|
|
7434
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Subtotal" }),
|
|
7435
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: total, currency }) })
|
|
7436
|
+
] }),
|
|
7437
|
+
hasDeposit && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7438
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(rowClass, classNames?.deposit), children: [
|
|
7439
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: labelClass, children: "Due now (deposit)" }),
|
|
7440
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsxRuntime.jsx(Price, { amount: depositDue, currency }) })
|
|
7441
|
+
] }),
|
|
7442
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(rowClass, "text-xs text-muted-foreground", classNames?.balance), children: [
|
|
7443
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Balance at appointment" }),
|
|
7444
|
+
/* @__PURE__ */ jsxRuntime.jsx(Price, { amount: balance, currency })
|
|
7445
|
+
] })
|
|
7446
|
+
] })
|
|
7447
|
+
] })
|
|
7448
|
+
]
|
|
7449
|
+
}
|
|
7450
|
+
);
|
|
7451
|
+
}
|
|
7314
7452
|
var FREQUENCY_LABELS = {
|
|
7315
7453
|
weekly: "Weekly",
|
|
7316
7454
|
biweekly: "Biweekly",
|
|
@@ -8675,7 +8813,7 @@ function groupSlots(slots) {
|
|
|
8675
8813
|
}
|
|
8676
8814
|
return ["morning", "afternoon", "evening"].filter((tod) => groups[tod]?.length).map((tod) => ({ label: TIME_OF_DAY_LABELS[tod], slots: groups[tod] }));
|
|
8677
8815
|
}
|
|
8678
|
-
function
|
|
8816
|
+
function formatTime2(timeStr) {
|
|
8679
8817
|
try {
|
|
8680
8818
|
const date = new Date(timeStr);
|
|
8681
8819
|
if (!isNaN(date.getTime())) {
|
|
@@ -8850,7 +8988,7 @@ function SlotPicker({
|
|
|
8850
8988
|
classNames?.slot
|
|
8851
8989
|
),
|
|
8852
8990
|
children: [
|
|
8853
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) :
|
|
8991
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime2(slot.start_time) }),
|
|
8854
8992
|
showPrice && slot.price && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8855
8993
|
"span",
|
|
8856
8994
|
{
|
|
@@ -8884,7 +9022,7 @@ function SlotPicker({
|
|
|
8884
9022
|
}
|
|
8885
9023
|
);
|
|
8886
9024
|
}
|
|
8887
|
-
function
|
|
9025
|
+
function formatDate2(dateStr) {
|
|
8888
9026
|
const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
|
|
8889
9027
|
return date.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric" });
|
|
8890
9028
|
}
|
|
@@ -9029,7 +9167,7 @@ function DateSlotPicker({
|
|
|
9029
9167
|
"flex flex-col items-center justify-center rounded-md border border-border bg-background px-1 py-2 text-center text-xs font-medium text-foreground transition-colors hover:border-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background data-[fully-booked]:cursor-not-allowed data-[fully-booked]:opacity-40",
|
|
9030
9168
|
classNames?.dateButton
|
|
9031
9169
|
),
|
|
9032
|
-
children:
|
|
9170
|
+
children: formatDate2(date)
|
|
9033
9171
|
},
|
|
9034
9172
|
date
|
|
9035
9173
|
);
|
|
@@ -9089,6 +9227,7 @@ function ProductCustomizer({
|
|
|
9089
9227
|
const [customerInputValues, setCustomerInputValues] = React14.useState({});
|
|
9090
9228
|
const [specialInstructions, setSpecialInstructions] = React14.useState("");
|
|
9091
9229
|
const [selectedSlot, setSelectedSlot] = React14.useState(null);
|
|
9230
|
+
const [selectedStaffId, setSelectedStaffId] = React14.useState(null);
|
|
9092
9231
|
const cart = useCart();
|
|
9093
9232
|
const currency = chunk7Y2O3E4D_js.getProductCurrency(product);
|
|
9094
9233
|
const productType = product.type || "product";
|
|
@@ -9116,7 +9255,16 @@ function ProductCustomizer({
|
|
|
9116
9255
|
setCustomerInputValues({});
|
|
9117
9256
|
setSpecialInstructions("");
|
|
9118
9257
|
setSelectedSlot(null);
|
|
9258
|
+
setSelectedStaffId(null);
|
|
9119
9259
|
}, [product.id, product.min_order_quantity]);
|
|
9260
|
+
const slotStaff = React14.useMemo(
|
|
9261
|
+
() => (selectedSlot?.available_staff ?? []).map((member) => ({
|
|
9262
|
+
id: member.staff_id,
|
|
9263
|
+
name: member.name
|
|
9264
|
+
})),
|
|
9265
|
+
[selectedSlot]
|
|
9266
|
+
);
|
|
9267
|
+
const selectedStaffName = selectedStaffId ? slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null : null;
|
|
9120
9268
|
const selectedAddOnOptions = React14.useMemo(() => {
|
|
9121
9269
|
if (!product.add_ons) return [];
|
|
9122
9270
|
const options = [];
|
|
@@ -9228,7 +9376,7 @@ function ProductCustomizer({
|
|
|
9228
9376
|
...isService && selectedSlot ? {
|
|
9229
9377
|
scheduledStart: selectedSlot.start_time,
|
|
9230
9378
|
scheduledEnd: selectedSlot.end_time,
|
|
9231
|
-
staffId: selectedSlot.available_staff?.[0]?.staff_id,
|
|
9379
|
+
staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,
|
|
9232
9380
|
resourceId: selectedSlot.available_resources?.[0]?.resource_id
|
|
9233
9381
|
} : {},
|
|
9234
9382
|
customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
|
|
@@ -9250,7 +9398,7 @@ function ProductCustomizer({
|
|
|
9250
9398
|
} finally {
|
|
9251
9399
|
setIsSubmitting(false);
|
|
9252
9400
|
}
|
|
9253
|
-
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);
|
|
9401
|
+
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);
|
|
9254
9402
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
|
|
9255
9403
|
isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9256
9404
|
CompositeSelector,
|
|
@@ -9282,11 +9430,30 @@ function ProductCustomizer({
|
|
|
9282
9430
|
{
|
|
9283
9431
|
serviceId: product.id,
|
|
9284
9432
|
selectedSlot,
|
|
9285
|
-
onSlotSelect: (slot) =>
|
|
9433
|
+
onSlotSelect: (slot) => {
|
|
9434
|
+
setSelectedSlot(slot);
|
|
9435
|
+
setSelectedStaffId(null);
|
|
9436
|
+
},
|
|
9286
9437
|
participantCount: quantity,
|
|
9287
9438
|
currency
|
|
9288
9439
|
}
|
|
9289
9440
|
),
|
|
9441
|
+
isService && slotStaff.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-cimplify-customizer-staff": true, children: [
|
|
9442
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Choose your specialist" }),
|
|
9443
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9444
|
+
StaffPicker,
|
|
9445
|
+
{
|
|
9446
|
+
staff: slotStaff,
|
|
9447
|
+
selectedStaffId,
|
|
9448
|
+
onStaffSelect: setSelectedStaffId,
|
|
9449
|
+
className: "flex flex-wrap gap-2",
|
|
9450
|
+
classNames: {
|
|
9451
|
+
option: "inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background",
|
|
9452
|
+
avatar: "w-6 h-6 rounded-full object-cover"
|
|
9453
|
+
}
|
|
9454
|
+
}
|
|
9455
|
+
)
|
|
9456
|
+
] }),
|
|
9290
9457
|
hasVariants && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9291
9458
|
VariantSelector,
|
|
9292
9459
|
{
|
|
@@ -9371,6 +9538,18 @@ function ProductCustomizer({
|
|
|
9371
9538
|
)
|
|
9372
9539
|
}
|
|
9373
9540
|
) }),
|
|
9541
|
+
isService && selectedSlot && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9542
|
+
BookingSummary,
|
|
9543
|
+
{
|
|
9544
|
+
slot: selectedSlot,
|
|
9545
|
+
total: displayTotalPrice,
|
|
9546
|
+
staffName: selectedStaffName,
|
|
9547
|
+
durationMinutes: product.duration_minutes,
|
|
9548
|
+
depositType: product.deposit_type,
|
|
9549
|
+
depositAmount: product.deposit_amount,
|
|
9550
|
+
currency
|
|
9551
|
+
}
|
|
9552
|
+
),
|
|
9374
9553
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9375
9554
|
"div",
|
|
9376
9555
|
{
|
|
@@ -12486,65 +12665,6 @@ function StoreNav({
|
|
|
12486
12665
|
] })
|
|
12487
12666
|
] });
|
|
12488
12667
|
}
|
|
12489
|
-
var ANY_VALUE = "__any__";
|
|
12490
|
-
function StaffPicker({
|
|
12491
|
-
staff,
|
|
12492
|
-
selectedStaffId,
|
|
12493
|
-
onStaffSelect,
|
|
12494
|
-
showAnyOption = true,
|
|
12495
|
-
anyLabel = "Any available",
|
|
12496
|
-
className,
|
|
12497
|
-
classNames
|
|
12498
|
-
}) {
|
|
12499
|
-
const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
|
|
12500
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12501
|
-
radioGroup.RadioGroup,
|
|
12502
|
-
{
|
|
12503
|
-
"data-cimplify-staff-picker": true,
|
|
12504
|
-
className: cn(className, classNames?.root),
|
|
12505
|
-
value: groupValue,
|
|
12506
|
-
onValueChange: (value) => {
|
|
12507
|
-
onStaffSelect?.(value === ANY_VALUE ? null : value);
|
|
12508
|
-
},
|
|
12509
|
-
children: [
|
|
12510
|
-
showAnyOption && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12511
|
-
radio.Radio.Root,
|
|
12512
|
-
{
|
|
12513
|
-
value: ANY_VALUE,
|
|
12514
|
-
"data-cimplify-staff-option": true,
|
|
12515
|
-
"data-selected": selectedStaffId === null || void 0,
|
|
12516
|
-
"data-any": true,
|
|
12517
|
-
className: classNames?.option,
|
|
12518
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
|
|
12519
|
-
}
|
|
12520
|
-
),
|
|
12521
|
-
staff.map((member) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12522
|
-
radio.Radio.Root,
|
|
12523
|
-
{
|
|
12524
|
-
value: member.id,
|
|
12525
|
-
"data-cimplify-staff-option": true,
|
|
12526
|
-
"data-selected": selectedStaffId === member.id || void 0,
|
|
12527
|
-
className: classNames?.option,
|
|
12528
|
-
children: [
|
|
12529
|
-
member.avatar_url && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12530
|
-
"img",
|
|
12531
|
-
{
|
|
12532
|
-
src: member.avatar_url,
|
|
12533
|
-
alt: member.name,
|
|
12534
|
-
"data-cimplify-staff-avatar": true,
|
|
12535
|
-
className: classNames?.avatar
|
|
12536
|
-
}
|
|
12537
|
-
),
|
|
12538
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
|
|
12539
|
-
member.bio && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
|
|
12540
|
-
]
|
|
12541
|
-
},
|
|
12542
|
-
member.id
|
|
12543
|
-
))
|
|
12544
|
-
]
|
|
12545
|
-
}
|
|
12546
|
-
);
|
|
12547
|
-
}
|
|
12548
12668
|
var STATUS_LABELS3 = {
|
|
12549
12669
|
pending: "Pending",
|
|
12550
12670
|
confirmed: "Confirmed",
|
|
@@ -16668,6 +16788,7 @@ exports.BillingPlanSelector = BillingPlanSelector;
|
|
|
16668
16788
|
exports.BookingCard = BookingCard;
|
|
16669
16789
|
exports.BookingList = BookingList;
|
|
16670
16790
|
exports.BookingPage = BookingPage;
|
|
16791
|
+
exports.BookingSummary = BookingSummary;
|
|
16671
16792
|
exports.BookingsPage = BookingsPage;
|
|
16672
16793
|
exports.BoxIcon24 = BoxIcon24;
|
|
16673
16794
|
exports.BundleProductCard = BundleProductCard;
|
package/dist/react.mjs
CHANGED
|
@@ -7306,6 +7306,144 @@ function formatDuration2(value, unit) {
|
|
|
7306
7306
|
const label = value === 1 ? labels.singular : labels.plural;
|
|
7307
7307
|
return `${value} ${label}`;
|
|
7308
7308
|
}
|
|
7309
|
+
var ANY_VALUE = "__any__";
|
|
7310
|
+
function StaffPicker({
|
|
7311
|
+
staff,
|
|
7312
|
+
selectedStaffId,
|
|
7313
|
+
onStaffSelect,
|
|
7314
|
+
showAnyOption = true,
|
|
7315
|
+
anyLabel = "Any available",
|
|
7316
|
+
className,
|
|
7317
|
+
classNames
|
|
7318
|
+
}) {
|
|
7319
|
+
const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
|
|
7320
|
+
return /* @__PURE__ */ jsxs(
|
|
7321
|
+
RadioGroup,
|
|
7322
|
+
{
|
|
7323
|
+
"data-cimplify-staff-picker": true,
|
|
7324
|
+
className: cn(className, classNames?.root),
|
|
7325
|
+
value: groupValue,
|
|
7326
|
+
onValueChange: (value) => {
|
|
7327
|
+
onStaffSelect?.(value === ANY_VALUE ? null : value);
|
|
7328
|
+
},
|
|
7329
|
+
children: [
|
|
7330
|
+
showAnyOption && /* @__PURE__ */ jsx(
|
|
7331
|
+
Radio.Root,
|
|
7332
|
+
{
|
|
7333
|
+
value: ANY_VALUE,
|
|
7334
|
+
"data-cimplify-staff-option": true,
|
|
7335
|
+
"data-selected": selectedStaffId === null || void 0,
|
|
7336
|
+
"data-any": true,
|
|
7337
|
+
className: classNames?.option,
|
|
7338
|
+
children: /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
|
|
7339
|
+
}
|
|
7340
|
+
),
|
|
7341
|
+
staff.map((member) => /* @__PURE__ */ jsxs(
|
|
7342
|
+
Radio.Root,
|
|
7343
|
+
{
|
|
7344
|
+
value: member.id,
|
|
7345
|
+
"data-cimplify-staff-option": true,
|
|
7346
|
+
"data-selected": selectedStaffId === member.id || void 0,
|
|
7347
|
+
className: classNames?.option,
|
|
7348
|
+
children: [
|
|
7349
|
+
member.avatar_url && /* @__PURE__ */ jsx(
|
|
7350
|
+
"img",
|
|
7351
|
+
{
|
|
7352
|
+
src: member.avatar_url,
|
|
7353
|
+
alt: member.name,
|
|
7354
|
+
"data-cimplify-staff-avatar": true,
|
|
7355
|
+
className: classNames?.avatar
|
|
7356
|
+
}
|
|
7357
|
+
),
|
|
7358
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
|
|
7359
|
+
member.bio && /* @__PURE__ */ jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
|
|
7360
|
+
]
|
|
7361
|
+
},
|
|
7362
|
+
member.id
|
|
7363
|
+
))
|
|
7364
|
+
]
|
|
7365
|
+
}
|
|
7366
|
+
);
|
|
7367
|
+
}
|
|
7368
|
+
function formatDate(value) {
|
|
7369
|
+
const date = new Date(value);
|
|
7370
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
7371
|
+
return date.toLocaleDateString(void 0, {
|
|
7372
|
+
weekday: "short",
|
|
7373
|
+
month: "short",
|
|
7374
|
+
day: "numeric"
|
|
7375
|
+
});
|
|
7376
|
+
}
|
|
7377
|
+
function formatTime(value) {
|
|
7378
|
+
const date = new Date(value);
|
|
7379
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
7380
|
+
return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
7381
|
+
}
|
|
7382
|
+
function BookingSummary({
|
|
7383
|
+
slot,
|
|
7384
|
+
total,
|
|
7385
|
+
staffName,
|
|
7386
|
+
durationMinutes,
|
|
7387
|
+
depositType,
|
|
7388
|
+
depositAmount,
|
|
7389
|
+
currency,
|
|
7390
|
+
className,
|
|
7391
|
+
classNames
|
|
7392
|
+
}) {
|
|
7393
|
+
const depositValue = depositAmount != null ? parsePrice(depositAmount) : 0;
|
|
7394
|
+
const depositDue = depositType === "percentage" ? total * depositValue / 100 : depositType === "fixed" ? depositValue : 0;
|
|
7395
|
+
const hasDeposit = depositDue > 0;
|
|
7396
|
+
const balance = Math.max(0, total - depositDue);
|
|
7397
|
+
const rowClass = cn("flex items-center justify-between", classNames?.row);
|
|
7398
|
+
const labelClass = cn("text-muted-foreground", classNames?.label);
|
|
7399
|
+
const valueClass = cn("font-medium", classNames?.value);
|
|
7400
|
+
return /* @__PURE__ */ jsxs(
|
|
7401
|
+
"div",
|
|
7402
|
+
{
|
|
7403
|
+
"data-cimplify-booking-summary": true,
|
|
7404
|
+
className: cn("rounded-lg border border-border p-4 space-y-3", className, classNames?.root),
|
|
7405
|
+
children: [
|
|
7406
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between", classNames?.header), children: [
|
|
7407
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: "Your booking" }),
|
|
7408
|
+
durationMinutes != null && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
7409
|
+
durationMinutes,
|
|
7410
|
+
" min"
|
|
7411
|
+
] })
|
|
7412
|
+
] }),
|
|
7413
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-sm", children: [
|
|
7414
|
+
staffName && /* @__PURE__ */ jsxs("div", { className: rowClass, children: [
|
|
7415
|
+
/* @__PURE__ */ jsx("span", { className: labelClass, children: "With" }),
|
|
7416
|
+
/* @__PURE__ */ jsx("span", { className: valueClass, children: staffName })
|
|
7417
|
+
] }),
|
|
7418
|
+
/* @__PURE__ */ jsxs("div", { className: rowClass, children: [
|
|
7419
|
+
/* @__PURE__ */ jsx("span", { className: labelClass, children: "Date" }),
|
|
7420
|
+
/* @__PURE__ */ jsx("span", { className: valueClass, children: formatDate(slot.start_time) })
|
|
7421
|
+
] }),
|
|
7422
|
+
/* @__PURE__ */ jsxs("div", { className: rowClass, children: [
|
|
7423
|
+
/* @__PURE__ */ jsx("span", { className: labelClass, children: "Time" }),
|
|
7424
|
+
/* @__PURE__ */ jsx("span", { className: valueClass, children: formatTime(slot.start_time) })
|
|
7425
|
+
] })
|
|
7426
|
+
] }),
|
|
7427
|
+
/* @__PURE__ */ jsxs("div", { className: cn("border-t border-border pt-3 space-y-1.5 text-sm", classNames?.totals), children: [
|
|
7428
|
+
/* @__PURE__ */ jsxs("div", { className: rowClass, children: [
|
|
7429
|
+
/* @__PURE__ */ jsx("span", { className: labelClass, children: "Subtotal" }),
|
|
7430
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsx(Price, { amount: total, currency }) })
|
|
7431
|
+
] }),
|
|
7432
|
+
hasDeposit && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7433
|
+
/* @__PURE__ */ jsxs("div", { className: cn(rowClass, classNames?.deposit), children: [
|
|
7434
|
+
/* @__PURE__ */ jsx("span", { className: labelClass, children: "Due now (deposit)" }),
|
|
7435
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: /* @__PURE__ */ jsx(Price, { amount: depositDue, currency }) })
|
|
7436
|
+
] }),
|
|
7437
|
+
/* @__PURE__ */ jsxs("div", { className: cn(rowClass, "text-xs text-muted-foreground", classNames?.balance), children: [
|
|
7438
|
+
/* @__PURE__ */ jsx("span", { children: "Balance at appointment" }),
|
|
7439
|
+
/* @__PURE__ */ jsx(Price, { amount: balance, currency })
|
|
7440
|
+
] })
|
|
7441
|
+
] })
|
|
7442
|
+
] })
|
|
7443
|
+
]
|
|
7444
|
+
}
|
|
7445
|
+
);
|
|
7446
|
+
}
|
|
7309
7447
|
var FREQUENCY_LABELS = {
|
|
7310
7448
|
weekly: "Weekly",
|
|
7311
7449
|
biweekly: "Biweekly",
|
|
@@ -8670,7 +8808,7 @@ function groupSlots(slots) {
|
|
|
8670
8808
|
}
|
|
8671
8809
|
return ["morning", "afternoon", "evening"].filter((tod) => groups[tod]?.length).map((tod) => ({ label: TIME_OF_DAY_LABELS[tod], slots: groups[tod] }));
|
|
8672
8810
|
}
|
|
8673
|
-
function
|
|
8811
|
+
function formatTime2(timeStr) {
|
|
8674
8812
|
try {
|
|
8675
8813
|
const date = new Date(timeStr);
|
|
8676
8814
|
if (!isNaN(date.getTime())) {
|
|
@@ -8845,7 +8983,7 @@ function SlotPicker({
|
|
|
8845
8983
|
classNames?.slot
|
|
8846
8984
|
),
|
|
8847
8985
|
children: [
|
|
8848
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) :
|
|
8986
|
+
/* @__PURE__ */ jsx("span", { "data-cimplify-slot-time": true, className: classNames?.slotTime, children: isMultiDay ? formatStaySummary(slot, durationUnit, durationValue) : formatTime2(slot.start_time) }),
|
|
8849
8987
|
showPrice && slot.price && /* @__PURE__ */ jsx(
|
|
8850
8988
|
"span",
|
|
8851
8989
|
{
|
|
@@ -8879,7 +9017,7 @@ function SlotPicker({
|
|
|
8879
9017
|
}
|
|
8880
9018
|
);
|
|
8881
9019
|
}
|
|
8882
|
-
function
|
|
9020
|
+
function formatDate2(dateStr) {
|
|
8883
9021
|
const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
|
|
8884
9022
|
return date.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric" });
|
|
8885
9023
|
}
|
|
@@ -9024,7 +9162,7 @@ function DateSlotPicker({
|
|
|
9024
9162
|
"flex flex-col items-center justify-center rounded-md border border-border bg-background px-1 py-2 text-center text-xs font-medium text-foreground transition-colors hover:border-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background data-[fully-booked]:cursor-not-allowed data-[fully-booked]:opacity-40",
|
|
9025
9163
|
classNames?.dateButton
|
|
9026
9164
|
),
|
|
9027
|
-
children:
|
|
9165
|
+
children: formatDate2(date)
|
|
9028
9166
|
},
|
|
9029
9167
|
date
|
|
9030
9168
|
);
|
|
@@ -9084,6 +9222,7 @@ function ProductCustomizer({
|
|
|
9084
9222
|
const [customerInputValues, setCustomerInputValues] = useState({});
|
|
9085
9223
|
const [specialInstructions, setSpecialInstructions] = useState("");
|
|
9086
9224
|
const [selectedSlot, setSelectedSlot] = useState(null);
|
|
9225
|
+
const [selectedStaffId, setSelectedStaffId] = useState(null);
|
|
9087
9226
|
const cart = useCart();
|
|
9088
9227
|
const currency = getProductCurrency(product);
|
|
9089
9228
|
const productType = product.type || "product";
|
|
@@ -9111,7 +9250,16 @@ function ProductCustomizer({
|
|
|
9111
9250
|
setCustomerInputValues({});
|
|
9112
9251
|
setSpecialInstructions("");
|
|
9113
9252
|
setSelectedSlot(null);
|
|
9253
|
+
setSelectedStaffId(null);
|
|
9114
9254
|
}, [product.id, product.min_order_quantity]);
|
|
9255
|
+
const slotStaff = useMemo(
|
|
9256
|
+
() => (selectedSlot?.available_staff ?? []).map((member) => ({
|
|
9257
|
+
id: member.staff_id,
|
|
9258
|
+
name: member.name
|
|
9259
|
+
})),
|
|
9260
|
+
[selectedSlot]
|
|
9261
|
+
);
|
|
9262
|
+
const selectedStaffName = selectedStaffId ? slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null : null;
|
|
9115
9263
|
const selectedAddOnOptions = useMemo(() => {
|
|
9116
9264
|
if (!product.add_ons) return [];
|
|
9117
9265
|
const options = [];
|
|
@@ -9223,7 +9371,7 @@ function ProductCustomizer({
|
|
|
9223
9371
|
...isService && selectedSlot ? {
|
|
9224
9372
|
scheduledStart: selectedSlot.start_time,
|
|
9225
9373
|
scheduledEnd: selectedSlot.end_time,
|
|
9226
|
-
staffId: selectedSlot.available_staff?.[0]?.staff_id,
|
|
9374
|
+
staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,
|
|
9227
9375
|
resourceId: selectedSlot.available_resources?.[0]?.resource_id
|
|
9228
9376
|
} : {},
|
|
9229
9377
|
customerInputs: Object.keys(customerInputValues).length > 0 ? Object.entries(customerInputValues).filter(([, v]) => v !== void 0 && v !== "").map(([fieldId, value]) => ({ field_id: fieldId, value })) : void 0,
|
|
@@ -9245,7 +9393,7 @@ function ProductCustomizer({
|
|
|
9245
9393
|
} finally {
|
|
9246
9394
|
setIsSubmitting(false);
|
|
9247
9395
|
}
|
|
9248
|
-
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);
|
|
9396
|
+
}, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);
|
|
9249
9397
|
return /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer": true, className: cn("space-y-6", className, classNames?.root), children: [
|
|
9250
9398
|
isComposite && product.groups && product.composite_id && /* @__PURE__ */ jsx(
|
|
9251
9399
|
CompositeSelector,
|
|
@@ -9277,11 +9425,30 @@ function ProductCustomizer({
|
|
|
9277
9425
|
{
|
|
9278
9426
|
serviceId: product.id,
|
|
9279
9427
|
selectedSlot,
|
|
9280
|
-
onSlotSelect: (slot) =>
|
|
9428
|
+
onSlotSelect: (slot) => {
|
|
9429
|
+
setSelectedSlot(slot);
|
|
9430
|
+
setSelectedStaffId(null);
|
|
9431
|
+
},
|
|
9281
9432
|
participantCount: quantity,
|
|
9282
9433
|
currency
|
|
9283
9434
|
}
|
|
9284
9435
|
),
|
|
9436
|
+
isService && slotStaff.length > 0 && /* @__PURE__ */ jsxs("div", { "data-cimplify-customizer-staff": true, children: [
|
|
9437
|
+
/* @__PURE__ */ jsx("label", { className: "block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3", children: "Choose your specialist" }),
|
|
9438
|
+
/* @__PURE__ */ jsx(
|
|
9439
|
+
StaffPicker,
|
|
9440
|
+
{
|
|
9441
|
+
staff: slotStaff,
|
|
9442
|
+
selectedStaffId,
|
|
9443
|
+
onStaffSelect: setSelectedStaffId,
|
|
9444
|
+
className: "flex flex-wrap gap-2",
|
|
9445
|
+
classNames: {
|
|
9446
|
+
option: "inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background",
|
|
9447
|
+
avatar: "w-6 h-6 rounded-full object-cover"
|
|
9448
|
+
}
|
|
9449
|
+
}
|
|
9450
|
+
)
|
|
9451
|
+
] }),
|
|
9285
9452
|
hasVariants && /* @__PURE__ */ jsx(
|
|
9286
9453
|
VariantSelector,
|
|
9287
9454
|
{
|
|
@@ -9366,6 +9533,18 @@ function ProductCustomizer({
|
|
|
9366
9533
|
)
|
|
9367
9534
|
}
|
|
9368
9535
|
) }),
|
|
9536
|
+
isService && selectedSlot && /* @__PURE__ */ jsx(
|
|
9537
|
+
BookingSummary,
|
|
9538
|
+
{
|
|
9539
|
+
slot: selectedSlot,
|
|
9540
|
+
total: displayTotalPrice,
|
|
9541
|
+
staffName: selectedStaffName,
|
|
9542
|
+
durationMinutes: product.duration_minutes,
|
|
9543
|
+
depositType: product.deposit_type,
|
|
9544
|
+
depositAmount: product.deposit_amount,
|
|
9545
|
+
currency
|
|
9546
|
+
}
|
|
9547
|
+
),
|
|
9369
9548
|
/* @__PURE__ */ jsxs(
|
|
9370
9549
|
"div",
|
|
9371
9550
|
{
|
|
@@ -12481,65 +12660,6 @@ function StoreNav({
|
|
|
12481
12660
|
] })
|
|
12482
12661
|
] });
|
|
12483
12662
|
}
|
|
12484
|
-
var ANY_VALUE = "__any__";
|
|
12485
|
-
function StaffPicker({
|
|
12486
|
-
staff,
|
|
12487
|
-
selectedStaffId,
|
|
12488
|
-
onStaffSelect,
|
|
12489
|
-
showAnyOption = true,
|
|
12490
|
-
anyLabel = "Any available",
|
|
12491
|
-
className,
|
|
12492
|
-
classNames
|
|
12493
|
-
}) {
|
|
12494
|
-
const groupValue = selectedStaffId === null ? ANY_VALUE : selectedStaffId ?? "";
|
|
12495
|
-
return /* @__PURE__ */ jsxs(
|
|
12496
|
-
RadioGroup,
|
|
12497
|
-
{
|
|
12498
|
-
"data-cimplify-staff-picker": true,
|
|
12499
|
-
className: cn(className, classNames?.root),
|
|
12500
|
-
value: groupValue,
|
|
12501
|
-
onValueChange: (value) => {
|
|
12502
|
-
onStaffSelect?.(value === ANY_VALUE ? null : value);
|
|
12503
|
-
},
|
|
12504
|
-
children: [
|
|
12505
|
-
showAnyOption && /* @__PURE__ */ jsx(
|
|
12506
|
-
Radio.Root,
|
|
12507
|
-
{
|
|
12508
|
-
value: ANY_VALUE,
|
|
12509
|
-
"data-cimplify-staff-option": true,
|
|
12510
|
-
"data-selected": selectedStaffId === null || void 0,
|
|
12511
|
-
"data-any": true,
|
|
12512
|
-
className: classNames?.option,
|
|
12513
|
-
children: /* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: anyLabel })
|
|
12514
|
-
}
|
|
12515
|
-
),
|
|
12516
|
-
staff.map((member) => /* @__PURE__ */ jsxs(
|
|
12517
|
-
Radio.Root,
|
|
12518
|
-
{
|
|
12519
|
-
value: member.id,
|
|
12520
|
-
"data-cimplify-staff-option": true,
|
|
12521
|
-
"data-selected": selectedStaffId === member.id || void 0,
|
|
12522
|
-
className: classNames?.option,
|
|
12523
|
-
children: [
|
|
12524
|
-
member.avatar_url && /* @__PURE__ */ jsx(
|
|
12525
|
-
"img",
|
|
12526
|
-
{
|
|
12527
|
-
src: member.avatar_url,
|
|
12528
|
-
alt: member.name,
|
|
12529
|
-
"data-cimplify-staff-avatar": true,
|
|
12530
|
-
className: classNames?.avatar
|
|
12531
|
-
}
|
|
12532
|
-
),
|
|
12533
|
-
/* @__PURE__ */ jsx("span", { "data-cimplify-staff-name": true, className: classNames?.name, children: member.name }),
|
|
12534
|
-
member.bio && /* @__PURE__ */ jsx("span", { "data-cimplify-staff-bio": true, className: classNames?.bio, children: member.bio })
|
|
12535
|
-
]
|
|
12536
|
-
},
|
|
12537
|
-
member.id
|
|
12538
|
-
))
|
|
12539
|
-
]
|
|
12540
|
-
}
|
|
12541
|
-
);
|
|
12542
|
-
}
|
|
12543
12663
|
var STATUS_LABELS3 = {
|
|
12544
12664
|
pending: "Pending",
|
|
12545
12665
|
confirmed: "Confirmed",
|
|
@@ -16632,4 +16752,4 @@ function SparkleIcon({ className }) {
|
|
|
16632
16752
|
);
|
|
16633
16753
|
}
|
|
16634
16754
|
|
|
16635
|
-
export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, Button, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
|
16755
|
+
export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingSummary, BookingsPage, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, Button, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"files": [
|
|
15
15
|
{
|
|
16
16
|
"path": "product-customizer.tsx",
|
|
17
|
-
"content": "\"use client\";\n\nimport React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport { Button } from \"@base-ui/react/button\";\nimport type {\n ProductWithDetails,\n VariantView,\n AddOnOption,\n ComponentSelectionInput,\n CompositePriceResult,\n} from \"@cimplify/sdk\";\nimport type { ProductBillingPlan } from \"@cimplify/sdk\";\nimport type { BundleSelectionInput } from \"@cimplify/sdk\";\nimport { parsePrice, getUnitPriceAtQuantity, getProductCurrency } from \"@cimplify/sdk\";\nimport { formatDuration } from \"./utils/format-duration\";\nimport { useCart, useQuote } from \"@cimplify/sdk/react\";\nimport type { AddToCartOptions } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { QuantitySelector } from \"@cimplify/sdk/react\";\nimport { VariantSelector } from \"@cimplify/sdk/react\";\nimport { AddOnSelector } from \"@cimplify/sdk/react\";\nimport { CompositeSelector } from \"@cimplify/sdk/react\";\nimport { BundleSelector } from \"@cimplify/sdk/react\";\nimport { BillingPlanSelector } from \"@cimplify/sdk/react\";\nimport { VolumePricing } from \"@cimplify/sdk/react\";\nimport { CustomerInputFields } from \"./customer-input-fields\";\nimport { DateSlotPicker } from \"@cimplify/sdk/react\";\nimport type { AvailableSlot } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface ProductCustomizerClassNames {\n root?: string;\n actions?: string;\n submitButton?: string;\n submitButtonAdded?: string;\n validation?: string;\n specialInstructions?: string;\n depositInfo?: string;\n allergens?: string;\n duration?: string;\n}\n\nexport interface ProductCustomizerProps {\n product: ProductWithDetails;\n onAddToCart?: (\n product: ProductWithDetails,\n quantity: number,\n options: AddToCartOptions,\n ) => void | Promise<void>;\n /** Lets the parent swap its gallery for `variant.images` on selection. */\n onVariantChange?: (\n variantId: string | undefined,\n variant: VariantView | undefined,\n ) => void;\n showSpecialInstructions?: boolean;\n className?: string;\n classNames?: ProductCustomizerClassNames;\n}\n\nexport function ProductCustomizer({\n product,\n onAddToCart,\n onVariantChange,\n showSpecialInstructions = true,\n className,\n classNames,\n}: ProductCustomizerProps): React.ReactElement {\n const [quantity, setQuantity] = useState(product.min_order_quantity ?? 1);\n const [isAdded, setIsAdded] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [selectedVariantId, setSelectedVariantId] = useState<string | undefined>();\n const [selectedVariant, setSelectedVariant] = useState<VariantView | undefined>();\n const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] = useState<string[]>([]);\n\n const [compositeSelections, setCompositeSelections] = useState<ComponentSelectionInput[]>([]);\n const [compositePrice, setCompositePrice] = useState<CompositePriceResult | null>(null);\n const [compositeReady, setCompositeReady] = useState(false);\n\n const [bundleSelections, setBundleSelections] = useState<BundleSelectionInput[]>([]);\n const [bundleTotalPrice, setBundleTotalPrice] = useState<number | null>(null);\n const [bundleReady, setBundleReady] = useState(false);\n const [selectedBillingPlan, setSelectedBillingPlan] = useState<ProductBillingPlan | null>(null);\n const [customerInputValues, setCustomerInputValues] = useState<Record<string, unknown>>({});\n const [specialInstructions, setSpecialInstructions] = useState(\"\");\n const [selectedSlot, setSelectedSlot] = useState<AvailableSlot | null>(null);\n\n const cart = useCart();\n\n const currency = getProductCurrency(product);\n const productType = product.type || \"product\";\n const isComposite = productType === \"composite\";\n const isBundle = productType === \"bundle\";\n const isDigital = productType === \"digital\";\n const isService = productType === \"service\";\n const isStandard = !isComposite && !isBundle;\n\n const hasVariants = isStandard && product.variants && product.variants.length > 0;\n const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;\n\n useEffect(() => {\n setQuantity(product.min_order_quantity ?? 1);\n setIsAdded(false);\n setIsSubmitting(false);\n setSelectedVariantId(undefined);\n setSelectedVariant(undefined);\n setSelectedAddOnOptionIds([]);\n setCompositeSelections([]);\n setCompositePrice(null);\n setCompositeReady(false);\n setBundleSelections([]);\n setBundleTotalPrice(null);\n setBundleReady(false);\n setSelectedBillingPlan(null);\n setCustomerInputValues({});\n setSpecialInstructions(\"\");\n setSelectedSlot(null);\n }, [product.id, product.min_order_quantity]);\n\n const selectedAddOnOptions = useMemo(() => {\n if (!product.add_ons) return [];\n const options: AddOnOption[] = [];\n for (const addOn of product.add_ons) {\n for (const option of addOn.options) {\n if (selectedAddOnOptionIds.includes(option.id)) {\n options.push(option);\n }\n }\n }\n return options;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const normalizedAddOnOptionIds = useMemo(() => {\n if (selectedAddOnOptionIds.length === 0) return [];\n return Array.from(new Set(selectedAddOnOptionIds.map((id) => id.trim()).filter(Boolean))).sort();\n }, [selectedAddOnOptionIds]);\n\n const localTotalPrice = useMemo(() => {\n if (isComposite && compositePrice) {\n return parsePrice(compositePrice.final_price) * quantity;\n }\n\n if (isBundle && bundleTotalPrice != null) {\n return bundleTotalPrice * quantity;\n }\n\n let price = parsePrice(product.default_price);\n\n if (selectedVariant?.price_adjustment) {\n price += parsePrice(selectedVariant.price_adjustment);\n }\n\n for (const option of selectedAddOnOptions) {\n if (option.default_price) {\n price += parsePrice(option.default_price);\n }\n }\n\n return price * quantity;\n }, [product.default_price, selectedVariant, selectedAddOnOptions, quantity, isComposite, compositePrice, isBundle, bundleTotalPrice]);\n\n const requiredAddOnsSatisfied = useMemo(() => {\n if (!product.add_ons) return true;\n\n for (const addOn of product.add_ons) {\n if (addOn.is_required) {\n const selectedInGroup = selectedAddOnOptionIds.filter((id) =>\n addOn.options.some((opt) => opt.id === id),\n ).length;\n\n const minRequired = addOn.min_selections || 1;\n if (selectedInGroup < minRequired) {\n return false;\n }\n }\n }\n return true;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const quoteInput = useMemo(\n () => ({\n productId: product.id,\n quantity,\n variantId: selectedVariantId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n }),\n [product.id, quantity, selectedVariantId, normalizedAddOnOptionIds, isBundle, bundleSelections, isComposite, compositeSelections],\n );\n\n const requiredInputsSatisfied = useMemo(() => {\n if (!product.input_fields || product.input_fields.length === 0) return true;\n return product.input_fields.every((field) => {\n if (!field.is_required) return true;\n const val = customerInputValues[field.id];\n return val !== undefined && val !== \"\" && val !== null;\n });\n }, [product.input_fields, customerInputValues]);\n\n const quoteEnabled = isComposite\n ? compositeReady && requiredInputsSatisfied\n : isBundle\n ? bundleReady && requiredInputsSatisfied\n : requiredAddOnsSatisfied && requiredInputsSatisfied;\n\n const { quote } = useQuote(quoteInput, {\n enabled: quoteEnabled,\n });\n\n const quoteId = quote?.quote_id;\n const quotedTotalPrice = useMemo(() => {\n if (!quote) return undefined;\n\n const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;\n const perUnit = priceInfo.pre_tax_price;\n if (perUnit === undefined || perUnit === null) return undefined;\n return parsePrice(perUnit) * quantity;\n }, [quote, quantity]);\n\n const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;\n\n const handleVariantChange = useCallback(\n (variantId: string | undefined, variant: VariantView | undefined) => {\n setSelectedVariantId(variantId);\n setSelectedVariant(variant);\n onVariantChange?.(variantId, variant);\n },\n [onVariantChange],\n );\n\n const addedTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => clearTimeout(addedTimerRef.current), []);\n\n const handleAddToCart = useCallback(async () => {\n if (isSubmitting) return;\n\n setIsSubmitting(true);\n\n const options: AddToCartOptions = {\n variantId: selectedVariantId,\n variant: selectedVariant\n ? { id: selectedVariant.id, name: selectedVariant.name || \"\", price_adjustment: selectedVariant.price_adjustment }\n : undefined,\n quoteId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n addOnOptions: selectedAddOnOptions.length > 0\n ? selectedAddOnOptions.map((opt) => ({\n id: opt.id,\n name: opt.name,\n add_on_id: opt.add_on_id,\n default_price: opt.default_price,\n }))\n : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n billingPlanId: selectedBillingPlan?.id,\n ...(isService && selectedSlot\n ? {\n scheduledStart: selectedSlot.start_time,\n scheduledEnd: selectedSlot.end_time,\n staffId: selectedSlot.available_staff?.[0]?.staff_id,\n resourceId: selectedSlot.available_resources?.[0]?.resource_id,\n }\n : {}),\n customerInputs: Object.keys(customerInputValues).length > 0\n ? Object.entries(customerInputValues)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([fieldId, value]) => ({ field_id: fieldId, value }))\n : undefined,\n specialInstructions: specialInstructions.trim() || undefined,\n };\n\n try {\n if (onAddToCart) {\n await onAddToCart(product, quantity, options);\n } else {\n await cart.addItem(product, quantity, options);\n }\n setIsAdded(true);\n clearTimeout(addedTimerRef.current);\n addedTimerRef.current = setTimeout(() => {\n setIsAdded(false);\n setQuantity(product.min_order_quantity ?? 1);\n }, 2000);\n } catch {\n // Caller handles errors via onAddToCart or cart hook error state\n } finally {\n setIsSubmitting(false);\n }\n }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, isSubmitting, onAddToCart, cart]);\n\n return (\n <div data-cimplify-customizer className={cn(\"space-y-6\", className, classNames?.root)}>\n {isComposite && product.groups && product.composite_id && (\n <CompositeSelector\n compositeId={product.composite_id}\n groups={product.groups}\n currency={currency}\n onSelectionsChange={setCompositeSelections}\n onPriceChange={setCompositePrice}\n onReady={setCompositeReady}\n skipPriceFetch\n />\n )}\n\n {isBundle && product.components && (\n <BundleSelector\n components={product.components}\n bundlePrice={product.bundle_price}\n discountValue={product.discount_value}\n pricingType={product.pricing_type}\n currency={currency}\n onSelectionsChange={setBundleSelections}\n onPriceChange={setBundleTotalPrice}\n onReady={setBundleReady}\n />\n )}\n\n {isService && (\n <DateSlotPicker\n serviceId={product.id}\n selectedSlot={selectedSlot}\n onSlotSelect={(slot) => setSelectedSlot(slot)}\n participantCount={quantity}\n currency={currency}\n />\n )}\n\n {hasVariants && (\n <VariantSelector\n variants={product.variants!}\n variantAxes={product.variant_axes}\n basePrice={product.default_price}\n currency={currency}\n selectedVariantId={selectedVariantId}\n onVariantChange={handleVariantChange}\n productName={product.name}\n />\n )}\n\n {hasAddOns && (\n <AddOnSelector\n addOns={product.add_ons!}\n selectedOptions={selectedAddOnOptionIds}\n onOptionsChange={setSelectedAddOnOptionIds}\n currency={currency}\n />\n )}\n\n {/* Billing plans */}\n {product.billing_plans && product.billing_plans.length > 0 && (\n <BillingPlanSelector\n productId={product.id}\n plans={product.billing_plans}\n currency={currency}\n onPlanSelect={setSelectedBillingPlan}\n selectedPlanId={selectedBillingPlan?.id ?? null}\n showOneTimePurchase\n />\n )}\n\n {/* Volume pricing tiers */}\n {product.quantity_pricing && product.quantity_pricing.length > 1 && (\n <VolumePricing\n tiers={product.quantity_pricing}\n currentQuantity={quantity}\n currency={currency}\n />\n )}\n\n {/* Customer input fields */}\n {product.input_fields && product.input_fields.length > 0 && (\n <CustomerInputFields\n fields={product.input_fields}\n values={customerInputValues}\n onChange={setCustomerInputValues}\n currency={currency}\n />\n )}\n\n {/* Deposit info for service products */}\n {product.deposit_type && product.deposit_type !== \"none\" && product.deposit_amount && (\n <div data-cimplify-customizer-deposit className={cn(\"text-sm text-muted-foreground\", classNames?.depositInfo)}>\n {product.deposit_type === \"fixed\" ? (\n <span>Deposit required: <Price amount={product.deposit_amount} currency={currency} /></span>\n ) : (\n <span>Deposit required: {parsePrice(product.deposit_amount)}%</span>\n )}\n </div>\n )}\n\n {/* Allergens */}\n {product.allergies && product.allergies.length > 0 && (\n <div data-cimplify-customizer-allergens className={cn(\"flex flex-wrap gap-1.5\", classNames?.allergens)}>\n {product.allergies.map((allergen) => (\n <span\n key={allergen}\n data-cimplify-allergen-tag\n className=\"inline-block text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground\"\n >\n {allergen}\n </span>\n ))}\n </div>\n )}\n\n {/* Service duration */}\n {isService && product.duration_minutes != null && (\n <div data-cimplify-customizer-duration className={cn(\"text-sm text-muted-foreground\", classNames?.duration)}>\n Duration: {formatDuration(product.duration_minutes, product.duration_unit)}\n </div>\n )}\n\n {/* Special instructions */}\n {showSpecialInstructions && !isDigital && (\n <div data-cimplify-customizer-special-instructions>\n <textarea\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n placeholder=\"Special instructions (e.g., no onions, extra sauce)\"\n rows={2}\n data-cimplify-customizer-textarea\n className={cn(\n \"w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-none\",\n classNames?.specialInstructions,\n )}\n />\n </div>\n )}\n\n <div\n data-cimplify-customizer-actions\n className={cn(\"pt-4 border-t border-border\", classNames?.actions)}\n >\n {!quoteEnabled && (\n <p\n id=\"cimplify-customizer-validation\"\n data-cimplify-customizer-validation\n className={cn(\"text-sm text-destructive mb-3\", classNames?.validation)}\n >\n Please select all required options\n </p>\n )}\n <div className=\"flex items-center gap-4\">\n <div className=\"flex flex-col gap-1\">\n <QuantitySelector\n value={quantity}\n onChange={setQuantity}\n min={product.min_order_quantity ?? 1}\n />\n {product.min_order_quantity && product.min_order_quantity > 1 && (\n <span data-cimplify-customizer-min-hint className=\"text-xs text-muted-foreground text-center\">\n Min. {product.min_order_quantity}\n </span>\n )}\n </div>\n\n {product.quantity_pricing && product.quantity_pricing.length > 0 && (\n <div data-cimplify-customizer-unit-price className=\"text-sm text-muted-foreground text-right shrink-0\">\n <Price amount={getUnitPriceAtQuantity(product.quantity_pricing, quantity, parsePrice(product.default_price))} currency={currency} className=\"font-medium text-foreground\" /> ea.\n </div>\n )}\n\n <Button\n onClick={handleAddToCart}\n disabled={isAdded || isSubmitting || !quoteEnabled}\n aria-describedby={!quoteEnabled ? \"cimplify-customizer-validation\" : undefined}\n data-cimplify-customizer-submit\n className={cn(\n \"flex-1 h-14 text-base bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed rounded-full\",\n isAdded && classNames?.submitButtonAdded,\n classNames?.submitButton,\n )}\n >\n {isAdded ? \"Added to Cart\" : (\n <>\n Add to Cart · <Price amount={displayTotalPrice} currency={currency} />\n </>\n )}\n </Button>\n </div>\n </div>\n\n </div>\n );\n}\n"
|
|
17
|
+
"content": "\"use client\";\n\nimport React, { useState, useCallback, useMemo, useEffect, useRef } from \"react\";\nimport { Button } from \"@base-ui/react/button\";\nimport type {\n ProductWithDetails,\n VariantView,\n AddOnOption,\n ComponentSelectionInput,\n CompositePriceResult,\n} from \"@cimplify/sdk\";\nimport type { ProductBillingPlan } from \"@cimplify/sdk\";\nimport type { BundleSelectionInput } from \"@cimplify/sdk\";\nimport { parsePrice, getUnitPriceAtQuantity, getProductCurrency } from \"@cimplify/sdk\";\nimport { formatDuration } from \"./utils/format-duration\";\nimport { useCart, useQuote } from \"@cimplify/sdk/react\";\nimport type { AddToCartOptions } from \"@cimplify/sdk/react\";\nimport { Price } from \"@cimplify/sdk/react\";\nimport { QuantitySelector } from \"@cimplify/sdk/react\";\nimport { VariantSelector } from \"@cimplify/sdk/react\";\nimport { AddOnSelector } from \"@cimplify/sdk/react\";\nimport { StaffPicker } from \"@cimplify/sdk/react\";\nimport { BookingSummary } from \"./booking-summary\";\nimport type { Staff } from \"@cimplify/sdk\";\nimport { CompositeSelector } from \"@cimplify/sdk/react\";\nimport { BundleSelector } from \"@cimplify/sdk/react\";\nimport { BillingPlanSelector } from \"@cimplify/sdk/react\";\nimport { VolumePricing } from \"@cimplify/sdk/react\";\nimport { CustomerInputFields } from \"./customer-input-fields\";\nimport { DateSlotPicker } from \"@cimplify/sdk/react\";\nimport type { AvailableSlot } from \"@cimplify/sdk\";\nimport { cn } from \"@cimplify/sdk/react\";\n\nexport interface ProductCustomizerClassNames {\n root?: string;\n actions?: string;\n submitButton?: string;\n submitButtonAdded?: string;\n validation?: string;\n specialInstructions?: string;\n depositInfo?: string;\n allergens?: string;\n duration?: string;\n}\n\nexport interface ProductCustomizerProps {\n product: ProductWithDetails;\n onAddToCart?: (\n product: ProductWithDetails,\n quantity: number,\n options: AddToCartOptions,\n ) => void | Promise<void>;\n /** Lets the parent swap its gallery for `variant.images` on selection. */\n onVariantChange?: (\n variantId: string | undefined,\n variant: VariantView | undefined,\n ) => void;\n showSpecialInstructions?: boolean;\n className?: string;\n classNames?: ProductCustomizerClassNames;\n}\n\nexport function ProductCustomizer({\n product,\n onAddToCart,\n onVariantChange,\n showSpecialInstructions = true,\n className,\n classNames,\n}: ProductCustomizerProps): React.ReactElement {\n const [quantity, setQuantity] = useState(product.min_order_quantity ?? 1);\n const [isAdded, setIsAdded] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [selectedVariantId, setSelectedVariantId] = useState<string | undefined>();\n const [selectedVariant, setSelectedVariant] = useState<VariantView | undefined>();\n const [selectedAddOnOptionIds, setSelectedAddOnOptionIds] = useState<string[]>([]);\n\n const [compositeSelections, setCompositeSelections] = useState<ComponentSelectionInput[]>([]);\n const [compositePrice, setCompositePrice] = useState<CompositePriceResult | null>(null);\n const [compositeReady, setCompositeReady] = useState(false);\n\n const [bundleSelections, setBundleSelections] = useState<BundleSelectionInput[]>([]);\n const [bundleTotalPrice, setBundleTotalPrice] = useState<number | null>(null);\n const [bundleReady, setBundleReady] = useState(false);\n const [selectedBillingPlan, setSelectedBillingPlan] = useState<ProductBillingPlan | null>(null);\n const [customerInputValues, setCustomerInputValues] = useState<Record<string, unknown>>({});\n const [specialInstructions, setSpecialInstructions] = useState(\"\");\n const [selectedSlot, setSelectedSlot] = useState<AvailableSlot | null>(null);\n const [selectedStaffId, setSelectedStaffId] = useState<string | null>(null);\n\n const cart = useCart();\n\n const currency = getProductCurrency(product);\n const productType = product.type || \"product\";\n const isComposite = productType === \"composite\";\n const isBundle = productType === \"bundle\";\n const isDigital = productType === \"digital\";\n const isService = productType === \"service\";\n const isStandard = !isComposite && !isBundle;\n\n const hasVariants = isStandard && product.variants && product.variants.length > 0;\n const hasAddOns = isStandard && product.add_ons && product.add_ons.length > 0;\n\n useEffect(() => {\n setQuantity(product.min_order_quantity ?? 1);\n setIsAdded(false);\n setIsSubmitting(false);\n setSelectedVariantId(undefined);\n setSelectedVariant(undefined);\n setSelectedAddOnOptionIds([]);\n setCompositeSelections([]);\n setCompositePrice(null);\n setCompositeReady(false);\n setBundleSelections([]);\n setBundleTotalPrice(null);\n setBundleReady(false);\n setSelectedBillingPlan(null);\n setCustomerInputValues({});\n setSpecialInstructions(\"\");\n setSelectedSlot(null);\n setSelectedStaffId(null);\n }, [product.id, product.min_order_quantity]);\n\n // Staff offered for the chosen slot. SlotStaffInfo carries id + name; richer\n // profiles (avatars/bios) would come from a staff roster fetch.\n const slotStaff = useMemo<Staff[]>(\n () =>\n (selectedSlot?.available_staff ?? []).map((member) => ({\n id: member.staff_id,\n name: member.name,\n })),\n [selectedSlot],\n );\n const selectedStaffName = selectedStaffId\n ? (slotStaff.find((member) => member.id === selectedStaffId)?.name ?? null)\n : null;\n\n const selectedAddOnOptions = useMemo(() => {\n if (!product.add_ons) return [];\n const options: AddOnOption[] = [];\n for (const addOn of product.add_ons) {\n for (const option of addOn.options) {\n if (selectedAddOnOptionIds.includes(option.id)) {\n options.push(option);\n }\n }\n }\n return options;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const normalizedAddOnOptionIds = useMemo(() => {\n if (selectedAddOnOptionIds.length === 0) return [];\n return Array.from(new Set(selectedAddOnOptionIds.map((id) => id.trim()).filter(Boolean))).sort();\n }, [selectedAddOnOptionIds]);\n\n const localTotalPrice = useMemo(() => {\n if (isComposite && compositePrice) {\n return parsePrice(compositePrice.final_price) * quantity;\n }\n\n if (isBundle && bundleTotalPrice != null) {\n return bundleTotalPrice * quantity;\n }\n\n let price = parsePrice(product.default_price);\n\n if (selectedVariant?.price_adjustment) {\n price += parsePrice(selectedVariant.price_adjustment);\n }\n\n for (const option of selectedAddOnOptions) {\n if (option.default_price) {\n price += parsePrice(option.default_price);\n }\n }\n\n return price * quantity;\n }, [product.default_price, selectedVariant, selectedAddOnOptions, quantity, isComposite, compositePrice, isBundle, bundleTotalPrice]);\n\n const requiredAddOnsSatisfied = useMemo(() => {\n if (!product.add_ons) return true;\n\n for (const addOn of product.add_ons) {\n if (addOn.is_required) {\n const selectedInGroup = selectedAddOnOptionIds.filter((id) =>\n addOn.options.some((opt) => opt.id === id),\n ).length;\n\n const minRequired = addOn.min_selections || 1;\n if (selectedInGroup < minRequired) {\n return false;\n }\n }\n }\n return true;\n }, [product.add_ons, selectedAddOnOptionIds]);\n\n const quoteInput = useMemo(\n () => ({\n productId: product.id,\n quantity,\n variantId: selectedVariantId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n }),\n [product.id, quantity, selectedVariantId, normalizedAddOnOptionIds, isBundle, bundleSelections, isComposite, compositeSelections],\n );\n\n const requiredInputsSatisfied = useMemo(() => {\n if (!product.input_fields || product.input_fields.length === 0) return true;\n return product.input_fields.every((field) => {\n if (!field.is_required) return true;\n const val = customerInputValues[field.id];\n return val !== undefined && val !== \"\" && val !== null;\n });\n }, [product.input_fields, customerInputValues]);\n\n const quoteEnabled = isComposite\n ? compositeReady && requiredInputsSatisfied\n : isBundle\n ? bundleReady && requiredInputsSatisfied\n : requiredAddOnsSatisfied && requiredInputsSatisfied;\n\n const { quote } = useQuote(quoteInput, {\n enabled: quoteEnabled,\n });\n\n const quoteId = quote?.quote_id;\n const quotedTotalPrice = useMemo(() => {\n if (!quote) return undefined;\n\n const priceInfo = quote.quoted_total_price_info ?? quote.final_price_info;\n const perUnit = priceInfo.pre_tax_price;\n if (perUnit === undefined || perUnit === null) return undefined;\n return parsePrice(perUnit) * quantity;\n }, [quote, quantity]);\n\n const displayTotalPrice = quotedTotalPrice ?? localTotalPrice;\n\n const handleVariantChange = useCallback(\n (variantId: string | undefined, variant: VariantView | undefined) => {\n setSelectedVariantId(variantId);\n setSelectedVariant(variant);\n onVariantChange?.(variantId, variant);\n },\n [onVariantChange],\n );\n\n const addedTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => () => clearTimeout(addedTimerRef.current), []);\n\n const handleAddToCart = useCallback(async () => {\n if (isSubmitting) return;\n\n setIsSubmitting(true);\n\n const options: AddToCartOptions = {\n variantId: selectedVariantId,\n variant: selectedVariant\n ? { id: selectedVariant.id, name: selectedVariant.name || \"\", price_adjustment: selectedVariant.price_adjustment }\n : undefined,\n quoteId,\n addOnOptionIds: normalizedAddOnOptionIds.length > 0 ? normalizedAddOnOptionIds : undefined,\n addOnOptions: selectedAddOnOptions.length > 0\n ? selectedAddOnOptions.map((opt) => ({\n id: opt.id,\n name: opt.name,\n add_on_id: opt.add_on_id,\n default_price: opt.default_price,\n }))\n : undefined,\n compositeSelections: isComposite && compositeSelections.length > 0 ? compositeSelections : undefined,\n bundleSelections: isBundle && bundleSelections.length > 0 ? bundleSelections : undefined,\n billingPlanId: selectedBillingPlan?.id,\n ...(isService && selectedSlot\n ? {\n scheduledStart: selectedSlot.start_time,\n scheduledEnd: selectedSlot.end_time,\n staffId: selectedStaffId ?? selectedSlot.available_staff?.[0]?.staff_id,\n resourceId: selectedSlot.available_resources?.[0]?.resource_id,\n }\n : {}),\n customerInputs: Object.keys(customerInputValues).length > 0\n ? Object.entries(customerInputValues)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([fieldId, value]) => ({ field_id: fieldId, value }))\n : undefined,\n specialInstructions: specialInstructions.trim() || undefined,\n };\n\n try {\n if (onAddToCart) {\n await onAddToCart(product, quantity, options);\n } else {\n await cart.addItem(product, quantity, options);\n }\n setIsAdded(true);\n clearTimeout(addedTimerRef.current);\n addedTimerRef.current = setTimeout(() => {\n setIsAdded(false);\n setQuantity(product.min_order_quantity ?? 1);\n }, 2000);\n } catch {\n // Caller handles errors via onAddToCart or cart hook error state\n } finally {\n setIsSubmitting(false);\n }\n }, [product, quantity, selectedVariantId, selectedVariant, quoteId, normalizedAddOnOptionIds, selectedAddOnOptions, isComposite, compositeSelections, isBundle, bundleSelections, selectedBillingPlan, customerInputValues, specialInstructions, isService, selectedSlot, selectedStaffId, isSubmitting, onAddToCart, cart]);\n\n return (\n <div data-cimplify-customizer className={cn(\"space-y-6\", className, classNames?.root)}>\n {isComposite && product.groups && product.composite_id && (\n <CompositeSelector\n compositeId={product.composite_id}\n groups={product.groups}\n currency={currency}\n onSelectionsChange={setCompositeSelections}\n onPriceChange={setCompositePrice}\n onReady={setCompositeReady}\n skipPriceFetch\n />\n )}\n\n {isBundle && product.components && (\n <BundleSelector\n components={product.components}\n bundlePrice={product.bundle_price}\n discountValue={product.discount_value}\n pricingType={product.pricing_type}\n currency={currency}\n onSelectionsChange={setBundleSelections}\n onPriceChange={setBundleTotalPrice}\n onReady={setBundleReady}\n />\n )}\n\n {isService && (\n <DateSlotPicker\n serviceId={product.id}\n selectedSlot={selectedSlot}\n onSlotSelect={(slot) => {\n setSelectedSlot(slot);\n setSelectedStaffId(null);\n }}\n participantCount={quantity}\n currency={currency}\n />\n )}\n\n {isService && slotStaff.length > 0 && (\n <div data-cimplify-customizer-staff>\n <label className=\"block text-xs font-medium uppercase tracking-wider text-muted-foreground mb-3\">\n Choose your specialist\n </label>\n <StaffPicker\n staff={slotStaff}\n selectedStaffId={selectedStaffId}\n onStaffSelect={setSelectedStaffId}\n className=\"flex flex-wrap gap-2\"\n classNames={{\n option:\n \"inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium transition-colors hover:border-foreground/40 cursor-pointer data-[selected]:border-foreground data-[selected]:bg-foreground data-[selected]:text-background\",\n avatar: \"w-6 h-6 rounded-full object-cover\",\n }}\n />\n </div>\n )}\n\n {hasVariants && (\n <VariantSelector\n variants={product.variants!}\n variantAxes={product.variant_axes}\n basePrice={product.default_price}\n currency={currency}\n selectedVariantId={selectedVariantId}\n onVariantChange={handleVariantChange}\n productName={product.name}\n />\n )}\n\n {hasAddOns && (\n <AddOnSelector\n addOns={product.add_ons!}\n selectedOptions={selectedAddOnOptionIds}\n onOptionsChange={setSelectedAddOnOptionIds}\n currency={currency}\n />\n )}\n\n {/* Billing plans */}\n {product.billing_plans && product.billing_plans.length > 0 && (\n <BillingPlanSelector\n productId={product.id}\n plans={product.billing_plans}\n currency={currency}\n onPlanSelect={setSelectedBillingPlan}\n selectedPlanId={selectedBillingPlan?.id ?? null}\n showOneTimePurchase\n />\n )}\n\n {/* Volume pricing tiers */}\n {product.quantity_pricing && product.quantity_pricing.length > 1 && (\n <VolumePricing\n tiers={product.quantity_pricing}\n currentQuantity={quantity}\n currency={currency}\n />\n )}\n\n {/* Customer input fields */}\n {product.input_fields && product.input_fields.length > 0 && (\n <CustomerInputFields\n fields={product.input_fields}\n values={customerInputValues}\n onChange={setCustomerInputValues}\n currency={currency}\n />\n )}\n\n {/* Deposit info for service products */}\n {product.deposit_type && product.deposit_type !== \"none\" && product.deposit_amount && (\n <div data-cimplify-customizer-deposit className={cn(\"text-sm text-muted-foreground\", classNames?.depositInfo)}>\n {product.deposit_type === \"fixed\" ? (\n <span>Deposit required: <Price amount={product.deposit_amount} currency={currency} /></span>\n ) : (\n <span>Deposit required: {parsePrice(product.deposit_amount)}%</span>\n )}\n </div>\n )}\n\n {/* Allergens */}\n {product.allergies && product.allergies.length > 0 && (\n <div data-cimplify-customizer-allergens className={cn(\"flex flex-wrap gap-1.5\", classNames?.allergens)}>\n {product.allergies.map((allergen) => (\n <span\n key={allergen}\n data-cimplify-allergen-tag\n className=\"inline-block text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground\"\n >\n {allergen}\n </span>\n ))}\n </div>\n )}\n\n {/* Service duration */}\n {isService && product.duration_minutes != null && (\n <div data-cimplify-customizer-duration className={cn(\"text-sm text-muted-foreground\", classNames?.duration)}>\n Duration: {formatDuration(product.duration_minutes, product.duration_unit)}\n </div>\n )}\n\n {/* Special instructions */}\n {showSpecialInstructions && !isDigital && (\n <div data-cimplify-customizer-special-instructions>\n <textarea\n value={specialInstructions}\n onChange={(e) => setSpecialInstructions(e.target.value)}\n placeholder=\"Special instructions (e.g., no onions, extra sauce)\"\n rows={2}\n data-cimplify-customizer-textarea\n className={cn(\n \"w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring resize-none\",\n classNames?.specialInstructions,\n )}\n />\n </div>\n )}\n\n {isService && selectedSlot && (\n <BookingSummary\n slot={selectedSlot}\n total={displayTotalPrice}\n staffName={selectedStaffName}\n durationMinutes={product.duration_minutes}\n depositType={product.deposit_type}\n depositAmount={product.deposit_amount}\n currency={currency}\n />\n )}\n\n <div\n data-cimplify-customizer-actions\n className={cn(\"pt-4 border-t border-border\", classNames?.actions)}\n >\n {!quoteEnabled && (\n <p\n id=\"cimplify-customizer-validation\"\n data-cimplify-customizer-validation\n className={cn(\"text-sm text-destructive mb-3\", classNames?.validation)}\n >\n Please select all required options\n </p>\n )}\n <div className=\"flex items-center gap-4\">\n <div className=\"flex flex-col gap-1\">\n <QuantitySelector\n value={quantity}\n onChange={setQuantity}\n min={product.min_order_quantity ?? 1}\n />\n {product.min_order_quantity && product.min_order_quantity > 1 && (\n <span data-cimplify-customizer-min-hint className=\"text-xs text-muted-foreground text-center\">\n Min. {product.min_order_quantity}\n </span>\n )}\n </div>\n\n {product.quantity_pricing && product.quantity_pricing.length > 0 && (\n <div data-cimplify-customizer-unit-price className=\"text-sm text-muted-foreground text-right shrink-0\">\n <Price amount={getUnitPriceAtQuantity(product.quantity_pricing, quantity, parsePrice(product.default_price))} currency={currency} className=\"font-medium text-foreground\" /> ea.\n </div>\n )}\n\n <Button\n onClick={handleAddToCart}\n disabled={isAdded || isSubmitting || !quoteEnabled}\n aria-describedby={!quoteEnabled ? \"cimplify-customizer-validation\" : undefined}\n data-cimplify-customizer-submit\n className={cn(\n \"flex-1 h-14 text-base bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed rounded-full\",\n isAdded && classNames?.submitButtonAdded,\n classNames?.submitButton,\n )}\n >\n {isAdded ? \"Added to Cart\" : (\n <>\n Add to Cart · <Price amount={displayTotalPrice} currency={currency} />\n </>\n )}\n </Button>\n </div>\n </div>\n\n </div>\n );\n}\n"
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
}
|