@cimplify/sdk 0.25.0 → 0.26.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.mjs CHANGED
@@ -7871,409 +7871,307 @@ function BookingList({
7871
7871
  booking.order_id
7872
7872
  )) });
7873
7873
  }
7874
-
7875
- // src/react/utils/format-duration.ts
7876
- var UNIT_LABELS3 = {
7877
- minutes: { singular: "min", plural: "min" },
7878
- hours: { singular: "hr", plural: "hrs" },
7879
- days: { singular: "day", plural: "days" },
7880
- nights: { singular: "night", plural: "nights" },
7881
- weeks: { singular: "week", plural: "weeks" },
7882
- months: { singular: "month", plural: "months" },
7883
- years: { singular: "year", plural: "years" }
7884
- };
7885
- function formatDuration4(value, unit) {
7886
- const resolved = unit ?? "minutes";
7887
- const labels = UNIT_LABELS3[resolved];
7888
- const label = value === 1 ? labels.singular : labels.plural;
7889
- return `${value} ${label}`;
7890
- }
7891
- var ASPECT_STYLES3 = {
7892
- square: { aspectRatio: "1/1" },
7893
- "4/3": { aspectRatio: "4/3" },
7894
- "16/10": { aspectRatio: "16/10" },
7895
- "3/4": { aspectRatio: "3/4" }
7896
- };
7897
- function ServiceCard({
7898
- service,
7899
- onBook,
7900
- href,
7901
- actionLabel = "Book",
7874
+ function DefaultCatalogueLayout({
7875
+ products,
7876
+ categories,
7877
+ facets,
7878
+ isLoading,
7879
+ selectedCategory,
7880
+ onCategoryChange,
7881
+ searchQuery,
7882
+ onSearchChange,
7883
+ sortBy,
7884
+ sortOrder,
7885
+ onSortChange,
7886
+ inStockOnly,
7887
+ onInStockChange,
7888
+ selectedTags,
7889
+ availableTags,
7890
+ onTagToggle,
7891
+ minPrice,
7892
+ maxPrice,
7893
+ onPriceRangeChange,
7894
+ page,
7895
+ totalPages,
7896
+ onPageChange,
7897
+ renderCard,
7902
7898
  renderImage,
7903
- children,
7904
- aspectRatio = "4/3",
7905
- className,
7906
- classNames
7899
+ renderLink,
7900
+ onQuickAdd,
7901
+ title = "Products",
7902
+ className
7907
7903
  }) {
7908
- const imageUrl = service.image_url;
7909
- const cardBody = children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
7910
- imageUrl && /* @__PURE__ */ jsx(
7911
- "div",
7912
- {
7913
- "data-cimplify-service-card-image-container": true,
7914
- className: cn("overflow-hidden rounded-t-xl", classNames?.imageContainer),
7915
- style: ASPECT_STYLES3[aspectRatio],
7916
- children: renderImage ? renderImage({
7917
- src: imageUrl,
7918
- alt: service.name,
7919
- className: classNames?.image
7920
- }) : /* @__PURE__ */ jsx(
7921
- "img",
7904
+ const hasSidebar = facets && facets.length > 0 || availableTags && availableTags.length > 0;
7905
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-layout": "default", className: cn("space-y-6", className), children: [
7906
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4", children: [
7907
+ /* @__PURE__ */ jsxs("div", { children: [
7908
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
7909
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-0.5", children: [
7910
+ products.length,
7911
+ " items"
7912
+ ] })
7913
+ ] }),
7914
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full sm:max-w-xs", children: [
7915
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
7916
+ /* @__PURE__ */ jsx(
7917
+ "input",
7922
7918
  {
7923
- src: imageUrl,
7924
- alt: service.name,
7925
- className: cn("w-full h-full object-cover transition-transform duration-300 group-hover:scale-105", classNames?.image),
7926
- "data-cimplify-service-card-image": true
7919
+ type: "search",
7920
+ value: searchQuery,
7921
+ onChange: (e) => onSearchChange(e.target.value),
7922
+ placeholder: "Search...",
7923
+ className: "w-full h-10 pl-10 pr-4 text-sm border border-border rounded-lg bg-background outline-none focus:ring-2 focus:ring-primary/10 focus:border-primary/30 transition-all"
7927
7924
  }
7928
7925
  )
7929
- }
7930
- ),
7931
- /* @__PURE__ */ jsxs("div", { "data-cimplify-service-card-body": true, className: cn("p-4 flex flex-col gap-1.5", classNames?.body), children: [
7932
- /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-name": true, className: cn("font-semibold text-foreground leading-tight", classNames?.name), children: service.name }),
7933
- service.description && /* @__PURE__ */ jsx(
7934
- "span",
7935
- {
7936
- "data-cimplify-service-card-description": true,
7937
- className: cn("text-sm text-muted-foreground line-clamp-2", classNames?.description),
7938
- children: service.description
7939
- }
7940
- ),
7941
- /* @__PURE__ */ jsxs("div", { "data-cimplify-service-card-meta": true, className: cn("flex items-center gap-2 mt-1 text-sm", classNames?.meta), children: [
7942
- /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-duration": true, className: cn("text-muted-foreground", classNames?.duration), children: formatDuration4(service.duration_minutes, service.duration_unit) }),
7943
- service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-price": true, className: cn("font-medium text-foreground", classNames?.price), children: /* @__PURE__ */ jsx(Price, { amount: service.price }) })
7944
7926
  ] })
7945
7927
  ] }),
7946
- !href && onBook && /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-action": true, className: cn("px-4 pb-4 pt-1 text-sm font-medium text-primary", classNames?.action), children: actionLabel })
7947
- ] });
7948
- const cardClasses = cn(
7949
- "group block w-full rounded-xl border border-border bg-background text-left transition-shadow duration-200 hover:shadow-md",
7950
- !service.is_available && "opacity-60",
7951
- className,
7952
- classNames?.root
7953
- );
7954
- if (href) {
7955
- return /* @__PURE__ */ jsx(
7956
- "a",
7957
- {
7958
- href,
7959
- "data-cimplify-service-card": true,
7960
- "data-available": service.is_available || void 0,
7961
- className: cn(cardClasses, "no-underline text-[inherit]"),
7962
- children: cardBody
7963
- }
7964
- );
7965
- }
7966
- return /* @__PURE__ */ jsx(
7967
- "button",
7968
- {
7969
- type: "button",
7970
- onClick: () => onBook?.(service),
7971
- disabled: !service.is_available,
7972
- "data-cimplify-service-card": true,
7973
- "data-available": service.is_available || void 0,
7974
- className: cn(cardClasses, "cursor-pointer font-[inherit] p-0 border-border"),
7975
- children: cardBody
7976
- }
7977
- );
7978
- }
7979
- function ServiceGrid({
7980
- services: servicesProp,
7981
- columns,
7982
- onServiceSelect,
7983
- getServiceHref,
7984
- renderCard,
7985
- renderImage,
7986
- availableOnly = true,
7987
- actionLabel,
7988
- emptyMessage = "No services available",
7989
- className,
7990
- classNames
7991
- }) {
7992
- const rawId = React3.useId();
7993
- const gridId = `cimplify-service-grid-${rawId.replace(/:/g, "")}`;
7994
- const { services: fetched, isLoading } = useServices({
7995
- enabled: servicesProp === void 0
7996
- });
7997
- const allServices = servicesProp ?? fetched;
7998
- const services = availableOnly ? allServices.filter((s) => s.is_available) : allServices;
7999
- const sm = columns?.sm ?? 1;
8000
- const md = columns?.md ?? 2;
8001
- const lg = columns?.lg ?? 3;
8002
- const xl = columns?.xl ?? 4;
8003
- if (isLoading && services.length === 0) {
8004
- return /* @__PURE__ */ jsx(
8005
- "div",
8006
- {
8007
- "data-cimplify-service-grid": true,
8008
- "aria-busy": "true",
8009
- className: cn(className, classNames?.root, classNames?.loading)
8010
- }
8011
- );
8012
- }
8013
- if (services.length === 0) {
8014
- return /* @__PURE__ */ jsx(
8015
- "div",
8016
- {
8017
- "data-cimplify-service-grid": true,
8018
- "data-empty": true,
8019
- className: cn(className, classNames?.root, classNames?.empty),
8020
- children: /* @__PURE__ */ jsx("p", { children: emptyMessage })
8021
- }
8022
- );
8023
- }
8024
- const css = [
8025
- `#${gridId}{display:grid;grid-template-columns:repeat(${sm},1fr);gap:1rem}`,
8026
- `@media(min-width:768px){#${gridId}{grid-template-columns:repeat(${md},1fr)}}`,
8027
- `@media(min-width:1024px){#${gridId}{grid-template-columns:repeat(${lg},1fr)}}`,
8028
- `@media(min-width:1280px){#${gridId}{grid-template-columns:repeat(${xl},1fr)}}`
8029
- ].join("");
8030
- return /* @__PURE__ */ jsxs(Fragment, { children: [
8031
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: css } }),
8032
- /* @__PURE__ */ jsx(
8033
- "div",
8034
- {
8035
- id: gridId,
8036
- "data-cimplify-service-grid": true,
8037
- className: cn(className, classNames?.root),
8038
- children: services.map((service) => /* @__PURE__ */ jsx(
8039
- "div",
7928
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
7929
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
7930
+ /* @__PURE__ */ jsx(
7931
+ "button",
8040
7932
  {
8041
- "data-cimplify-service-grid-item": true,
8042
- className: classNames?.item,
8043
- children: renderCard ? renderCard(service) : /* @__PURE__ */ jsx(
8044
- ServiceCard,
8045
- {
8046
- service,
8047
- onBook: onServiceSelect,
8048
- href: getServiceHref?.(service),
8049
- actionLabel,
8050
- renderImage
8051
- }
8052
- )
7933
+ onClick: () => onCategoryChange(null),
7934
+ className: cn(
7935
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
7936
+ !selectedCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
7937
+ ),
7938
+ children: "All"
7939
+ }
7940
+ ),
7941
+ categories.map((cat) => /* @__PURE__ */ jsx(
7942
+ "button",
7943
+ {
7944
+ onClick: () => onCategoryChange(selectedCategory === cat.id ? null : cat.id),
7945
+ className: cn(
7946
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
7947
+ selectedCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
7948
+ ),
7949
+ children: cat.name
8053
7950
  },
8054
- service.id
7951
+ cat.id
8055
7952
  ))
8056
- }
8057
- )
8058
- ] });
8059
- }
8060
- function CataloguePage({
8061
- title = "Products",
8062
- products: productsProp,
8063
- categories: categoriesProp,
8064
- showFilter = true,
8065
- showSearch = true,
8066
- showSort = false,
8067
- showInStockFilter = false,
8068
- showPriceRange = false,
8069
- showTagsFilter = false,
8070
- availableTags,
8071
- defaultSort,
8072
- pageSize,
8073
- onProductClick,
8074
- onCategoryClick,
8075
- renderCard,
8076
- renderImage,
8077
- columns,
8078
- className,
8079
- classNames
8080
- }) {
8081
- const [selectedCategoryId, setSelectedCategoryId] = useState(null);
8082
- const [searchQuery, setSearchQuery] = useState("");
8083
- const [sortBy, setSortBy] = useState(defaultSort?.by ?? "name");
8084
- const [sortOrder, setSortOrder] = useState(defaultSort?.order ?? "asc");
8085
- const [inStockOnly, setInStockOnly] = useState(false);
8086
- const [selectedTags, setSelectedTags] = useState([]);
8087
- const [minPrice, setMinPrice] = useState("");
8088
- const [maxPrice, setMaxPrice] = useState("");
8089
- const [page, setPage] = useState(1);
8090
- const debouncedSearch = useDebounce(searchQuery, 300);
8091
- const { products: fetchedProducts, isLoading: productsLoading, pagination } = useProducts({
8092
- enabled: productsProp === void 0,
8093
- category: selectedCategoryId ?? void 0,
8094
- search: debouncedSearch.length >= 2 ? debouncedSearch : void 0,
8095
- sort_by: sortBy,
8096
- sort_order: sortOrder,
8097
- in_stock: inStockOnly || void 0,
8098
- tags: selectedTags.length > 0 ? selectedTags : void 0,
8099
- min_price: minPrice ? parseFloat(minPrice) : void 0,
8100
- max_price: maxPrice ? parseFloat(maxPrice) : void 0,
8101
- page,
8102
- limit: pageSize
8103
- });
8104
- const { categories: fetchedCategories } = useCategories({
8105
- enabled: showFilter && categoriesProp === void 0
8106
- });
8107
- const allProducts = productsProp ?? fetchedProducts;
8108
- const categories = categoriesProp ?? fetchedCategories;
8109
- const handleCategorySelect = useCallback(
8110
- (id) => {
8111
- setSelectedCategoryId(id);
8112
- setPage(1);
8113
- if (id) {
8114
- const cat = categories.find((c) => c.id === id);
8115
- if (cat) onCategoryClick?.(cat);
8116
- }
8117
- },
8118
- [categories, onCategoryClick]
8119
- );
8120
- const handleTagToggle = useCallback((tag) => {
8121
- setSelectedTags(
8122
- (prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
8123
- );
8124
- setPage(1);
8125
- }, []);
8126
- const totalPages = pagination?.total_pages ?? 1;
8127
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-page": true, className: cn(className, classNames?.root), children: [
8128
- /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-header": true, className: classNames?.header, children: [
8129
- /* @__PURE__ */ jsx("h1", { "data-cimplify-catalogue-title": true, className: classNames?.title, children: title }),
8130
- showSearch && /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-search": true, className: classNames?.searchContainer, children: /* @__PURE__ */ jsx(
8131
- SearchInput,
8132
- {
8133
- onResultClick: onProductClick,
8134
- searchOptions: { category: selectedCategoryId ?? void 0 }
8135
- }
8136
- ) })
8137
- ] }),
8138
- showFilter && categories.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-filter": true, className: classNames?.filterContainer, children: /* @__PURE__ */ jsx(
8139
- CategoryFilter,
8140
- {
8141
- selectedId: selectedCategoryId,
8142
- onSelect: handleCategorySelect
8143
- }
8144
- ) }),
8145
- (showSort || showInStockFilter || showPriceRange || showTagsFilter) && /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-toolbar": true, className: cn("flex flex-wrap items-center gap-3", classNames?.toolbar), children: [
8146
- showSort && /* @__PURE__ */ jsxs(
7953
+ ] }),
7954
+ /* @__PURE__ */ jsxs(
8147
7955
  "select",
8148
7956
  {
8149
- "data-cimplify-sort": true,
8150
7957
  value: `${sortBy}:${sortOrder}`,
8151
7958
  onChange: (e) => {
8152
7959
  const [by, order] = e.target.value.split(":");
8153
- setSortBy(by);
8154
- setSortOrder(order);
8155
- setPage(1);
7960
+ onSortChange(by, order);
8156
7961
  },
8157
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm",
7962
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none shrink-0",
8158
7963
  children: [
8159
- /* @__PURE__ */ jsx("option", { value: "name:asc", children: "Name A\u2013Z" }),
8160
- /* @__PURE__ */ jsx("option", { value: "name:desc", children: "Name Z\u2013A" }),
7964
+ /* @__PURE__ */ jsx("option", { value: "created_at:desc", children: "Newest" }),
8161
7965
  /* @__PURE__ */ jsx("option", { value: "price:asc", children: "Price: Low to High" }),
8162
7966
  /* @__PURE__ */ jsx("option", { value: "price:desc", children: "Price: High to Low" }),
8163
- /* @__PURE__ */ jsx("option", { value: "created_at:desc", children: "Newest" }),
8164
- /* @__PURE__ */ jsx("option", { value: "created_at:asc", children: "Oldest" }),
8165
- /* @__PURE__ */ jsx("option", { value: "updated_at:desc", children: "Recently Updated" })
7967
+ /* @__PURE__ */ jsx("option", { value: "name:asc", children: "Name: A-Z" })
8166
7968
  ]
8167
7969
  }
8168
- ),
8169
- showInStockFilter && /* @__PURE__ */ jsxs("label", { "data-cimplify-stock-filter": true, className: "flex items-center gap-1.5 text-sm cursor-pointer", children: [
8170
- /* @__PURE__ */ jsx(
8171
- "input",
8172
- {
8173
- type: "checkbox",
8174
- checked: inStockOnly,
8175
- onChange: (e) => {
8176
- setInStockOnly(e.target.checked);
8177
- setPage(1);
8178
- },
8179
- className: "accent-primary"
8180
- }
8181
- ),
8182
- "In stock only"
7970
+ )
7971
+ ] }),
7972
+ /* @__PURE__ */ jsxs("div", { className: hasSidebar ? "flex gap-6" : "", children: [
7973
+ hasSidebar && /* @__PURE__ */ jsxs("aside", { className: "hidden lg:block w-60 shrink-0 space-y-6", children: [
7974
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
7975
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "In stock only" }),
7976
+ /* @__PURE__ */ jsx(
7977
+ "button",
7978
+ {
7979
+ onClick: () => onInStockChange(!inStockOnly),
7980
+ className: cn("w-10 h-6 rounded-full transition-colors relative", inStockOnly ? "bg-foreground" : "bg-border"),
7981
+ children: /* @__PURE__ */ jsx("span", { className: cn("absolute top-1 w-4 h-4 rounded-full bg-background transition-transform shadow-sm", inStockOnly ? "left-5" : "left-1") })
7982
+ }
7983
+ )
7984
+ ] }),
7985
+ /* @__PURE__ */ jsxs("div", { children: [
7986
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: "Price Range" }),
7987
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
7988
+ /* @__PURE__ */ jsx(
7989
+ "input",
7990
+ {
7991
+ type: "number",
7992
+ placeholder: "Min",
7993
+ value: minPrice,
7994
+ onChange: (e) => onPriceRangeChange(e.target.value, maxPrice),
7995
+ className: "w-full rounded-lg border border-border px-2 py-1.5 text-xs bg-background outline-none focus:ring-1 focus:ring-primary/20"
7996
+ }
7997
+ ),
7998
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: "\u2013" }),
7999
+ /* @__PURE__ */ jsx(
8000
+ "input",
8001
+ {
8002
+ type: "number",
8003
+ placeholder: "Max",
8004
+ value: maxPrice,
8005
+ onChange: (e) => onPriceRangeChange(minPrice, e.target.value),
8006
+ className: "w-full rounded-lg border border-border px-2 py-1.5 text-xs bg-background outline-none focus:ring-1 focus:ring-primary/20"
8007
+ }
8008
+ )
8009
+ ] })
8010
+ ] }),
8011
+ facets?.map((facet) => /* @__PURE__ */ jsxs("div", { children: [
8012
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: facet.name }),
8013
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: facet.values.slice(0, 8).map((fv) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
8014
+ /* @__PURE__ */ jsx("input", { type: "checkbox", className: "w-3.5 h-3.5 accent-foreground rounded" }),
8015
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors flex-1", children: fv.value }),
8016
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60", children: fv.count })
8017
+ ] }, fv.value)) })
8018
+ ] }, facet.slug)),
8019
+ availableTags && availableTags.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
8020
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: "Tags" }),
8021
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: availableTags.map((tag) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
8022
+ /* @__PURE__ */ jsx(
8023
+ "input",
8024
+ {
8025
+ type: "checkbox",
8026
+ checked: selectedTags.includes(tag),
8027
+ onChange: () => onTagToggle(tag),
8028
+ className: "w-3.5 h-3.5 accent-foreground rounded"
8029
+ }
8030
+ ),
8031
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors", children: tag })
8032
+ ] }, tag)) })
8033
+ ] })
8183
8034
  ] }),
8184
- showPriceRange && /* @__PURE__ */ jsxs("div", { "data-cimplify-price-range": true, className: "flex items-center gap-1.5", children: [
8035
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
8036
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4 animate-pulse", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
8037
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
8038
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
8039
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
8040
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
8041
+ ] })
8042
+ ] }, i)) }) : products.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
8043
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No products found" }),
8044
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try adjusting your filters" })
8045
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: products.map(
8046
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
8047
+ ProductCard,
8048
+ {
8049
+ product,
8050
+ renderImage,
8051
+ renderLink,
8052
+ onQuickAdd
8053
+ },
8054
+ product.id
8055
+ )
8056
+ ) }),
8057
+ totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 pt-8", children: [
8058
+ /* @__PURE__ */ jsx(
8059
+ "button",
8060
+ {
8061
+ disabled: page <= 1,
8062
+ onClick: () => onPageChange(page - 1),
8063
+ className: "text-sm px-3 py-1.5 border border-border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
8064
+ children: "Previous"
8065
+ }
8066
+ ),
8067
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums px-2", children: [
8068
+ page,
8069
+ " / ",
8070
+ totalPages
8071
+ ] }),
8072
+ /* @__PURE__ */ jsx(
8073
+ "button",
8074
+ {
8075
+ disabled: page >= totalPages,
8076
+ onClick: () => onPageChange(page + 1),
8077
+ className: "text-sm px-3 py-1.5 border border-border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
8078
+ children: "Next"
8079
+ }
8080
+ )
8081
+ ] })
8082
+ ] })
8083
+ ] })
8084
+ ] });
8085
+ }
8086
+ function CompactCatalogueLayout({
8087
+ products,
8088
+ categories,
8089
+ isLoading,
8090
+ selectedCategory,
8091
+ onCategoryChange,
8092
+ searchQuery,
8093
+ onSearchChange,
8094
+ renderCard,
8095
+ renderImage,
8096
+ renderLink,
8097
+ onQuickAdd,
8098
+ title = "Menu",
8099
+ className
8100
+ }) {
8101
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-layout": "compact", className: cn("space-y-6", className), children: [
8102
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
8103
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-3", children: [
8104
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1 flex-1", children: [
8185
8105
  /* @__PURE__ */ jsx(
8186
- "input",
8106
+ "button",
8187
8107
  {
8188
- type: "number",
8189
- placeholder: "Min",
8190
- value: minPrice,
8191
- onChange: (e) => {
8192
- setMinPrice(e.target.value);
8193
- setPage(1);
8194
- },
8195
- className: "w-20 rounded-md border border-input bg-background px-2 py-1.5 text-sm",
8196
- min: 0,
8197
- step: "0.01"
8108
+ onClick: () => onCategoryChange(null),
8109
+ className: cn(
8110
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8111
+ !selectedCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8112
+ ),
8113
+ children: "All"
8198
8114
  }
8199
8115
  ),
8200
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "\u2013" }),
8116
+ categories.map((cat) => /* @__PURE__ */ jsx(
8117
+ "button",
8118
+ {
8119
+ onClick: () => onCategoryChange(selectedCategory === cat.id ? null : cat.id),
8120
+ className: cn(
8121
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8122
+ selectedCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8123
+ ),
8124
+ children: cat.name
8125
+ },
8126
+ cat.id
8127
+ ))
8128
+ ] }),
8129
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full sm:max-w-[200px]", children: [
8130
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
8201
8131
  /* @__PURE__ */ jsx(
8202
8132
  "input",
8203
8133
  {
8204
- type: "number",
8205
- placeholder: "Max",
8206
- value: maxPrice,
8207
- onChange: (e) => {
8208
- setMaxPrice(e.target.value);
8209
- setPage(1);
8210
- },
8211
- className: "w-20 rounded-md border border-input bg-background px-2 py-1.5 text-sm",
8212
- min: 0,
8213
- step: "0.01"
8134
+ type: "search",
8135
+ value: searchQuery,
8136
+ onChange: (e) => onSearchChange(e.target.value),
8137
+ placeholder: "Search...",
8138
+ className: "w-full h-9 pl-10 pr-3 text-sm border border-border rounded-lg bg-background outline-none focus:ring-2 focus:ring-primary/10 transition-all"
8214
8139
  }
8215
8140
  )
8216
- ] }),
8217
- showTagsFilter && availableTags && availableTags.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-tags-filter": true, className: "flex flex-wrap gap-1.5", children: availableTags.map((tag) => /* @__PURE__ */ jsx(
8218
- "button",
8219
- {
8220
- type: "button",
8221
- onClick: () => handleTagToggle(tag),
8222
- className: cn(
8223
- "rounded-full px-3 py-1 text-xs font-medium border transition-colors",
8224
- selectedTags.includes(tag) ? "bg-primary text-primary-foreground border-primary" : "bg-background text-foreground border-input hover:bg-muted"
8225
- ),
8226
- children: tag
8227
- },
8228
- tag
8229
- )) })
8141
+ ] })
8230
8142
  ] }),
8231
- /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-grid": true, className: classNames?.gridContainer, children: productsLoading && !productsProp ? /* @__PURE__ */ jsx(
8232
- "div",
8233
- {
8234
- "data-cimplify-catalogue-loading": true,
8235
- "aria-busy": "true",
8236
- className: classNames?.loading
8237
- }
8238
- ) : /* @__PURE__ */ jsx(
8239
- ProductGrid,
8240
- {
8241
- products: allProducts,
8242
- renderCard,
8243
- renderImage,
8244
- columns,
8245
- emptyMessage: "No products found"
8246
- }
8247
- ) }),
8248
- totalPages > 1 && /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-pagination": true, className: cn("flex items-center justify-center gap-2 pt-6", classNames?.pagination), children: [
8249
- /* @__PURE__ */ jsx(
8250
- "button",
8251
- {
8252
- type: "button",
8253
- disabled: page <= 1,
8254
- onClick: () => setPage((p) => Math.max(1, p - 1)),
8255
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm disabled:opacity-40",
8256
- children: "Previous"
8257
- }
8258
- ),
8259
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums", children: [
8260
- page,
8261
- " / ",
8262
- totalPages
8263
- ] }),
8264
- /* @__PURE__ */ jsx(
8265
- "button",
8143
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5 animate-pulse", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
8144
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
8145
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
8146
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
8147
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
8148
+ ] })
8149
+ ] }, i)) }) : products.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
8150
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No items found" }),
8151
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different category or search" })
8152
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: products.map(
8153
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
8154
+ ProductCard,
8266
8155
  {
8267
- type: "button",
8268
- disabled: page >= totalPages,
8269
- onClick: () => setPage((p) => p + 1),
8270
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm disabled:opacity-40",
8271
- children: "Next"
8272
- }
8156
+ product,
8157
+ renderImage,
8158
+ renderLink,
8159
+ onQuickAdd
8160
+ },
8161
+ product.id
8273
8162
  )
8274
- ] })
8163
+ ) })
8275
8164
  ] });
8276
8165
  }
8166
+ var CatalogueTemplate = /* @__PURE__ */ ((CatalogueTemplate2) => {
8167
+ CatalogueTemplate2["Default"] = "default";
8168
+ CatalogueTemplate2["Compact"] = "compact";
8169
+ return CatalogueTemplate2;
8170
+ })(CatalogueTemplate || {});
8171
+ var BUILT_IN_LAYOUTS = {
8172
+ ["default" /* Default */]: DefaultCatalogueLayout,
8173
+ ["compact" /* Compact */]: CompactCatalogueLayout
8174
+ };
8277
8175
  function useDebounce(value, delay) {
8278
8176
  const [debounced, setDebounced] = React3.useState(value);
8279
8177
  React3.useEffect(() => {
@@ -8282,6 +8180,109 @@ function useDebounce(value, delay) {
8282
8180
  }, [value, delay]);
8283
8181
  return debounced;
8284
8182
  }
8183
+ function CataloguePage({
8184
+ template,
8185
+ layouts,
8186
+ title,
8187
+ products: productsProp,
8188
+ categories: categoriesProp,
8189
+ facets,
8190
+ availableTags,
8191
+ pageSize,
8192
+ defaultSort,
8193
+ renderCard,
8194
+ renderImage,
8195
+ renderLink,
8196
+ onQuickAdd,
8197
+ onProductClick,
8198
+ className,
8199
+ classNames
8200
+ }) {
8201
+ const [selectedCategory, setSelectedCategory] = useState(null);
8202
+ const [searchQuery, setSearchQuery] = useState("");
8203
+ const [sortBy, setSortBy] = useState(defaultSort?.by ?? "created_at");
8204
+ const [sortOrder, setSortOrder] = useState(defaultSort?.order ?? "desc");
8205
+ const [inStockOnly, setInStockOnly] = useState(false);
8206
+ const [selectedTags, setSelectedTags] = useState([]);
8207
+ const [minPrice, setMinPrice] = useState("");
8208
+ const [maxPrice, setMaxPrice] = useState("");
8209
+ const [page, setPage] = useState(1);
8210
+ const debouncedSearch = useDebounce(searchQuery, 300);
8211
+ const { products: fetchedProducts, isLoading, pagination } = useProducts({
8212
+ enabled: productsProp === void 0,
8213
+ category: selectedCategory ?? void 0,
8214
+ search: debouncedSearch.length >= 2 ? debouncedSearch : void 0,
8215
+ sort_by: sortBy,
8216
+ sort_order: sortOrder,
8217
+ in_stock: inStockOnly || void 0,
8218
+ tags: selectedTags.length > 0 ? selectedTags : void 0,
8219
+ min_price: minPrice ? parseFloat(minPrice) : void 0,
8220
+ max_price: maxPrice ? parseFloat(maxPrice) : void 0,
8221
+ page,
8222
+ limit: pageSize
8223
+ });
8224
+ const { categories: fetchedCategories } = useCategories({
8225
+ enabled: categoriesProp === void 0
8226
+ });
8227
+ const products = productsProp ?? fetchedProducts;
8228
+ const categories = categoriesProp ?? fetchedCategories;
8229
+ const totalPages = pagination?.total_pages ?? 1;
8230
+ const handleCategoryChange = useCallback((id) => {
8231
+ setSelectedCategory(id);
8232
+ setPage(1);
8233
+ }, []);
8234
+ const handleSortChange = useCallback((by, order) => {
8235
+ setSortBy(by);
8236
+ setSortOrder(order);
8237
+ setPage(1);
8238
+ }, []);
8239
+ const handleTagToggle = useCallback((tag) => {
8240
+ setSelectedTags(
8241
+ (prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
8242
+ );
8243
+ setPage(1);
8244
+ }, []);
8245
+ const handlePriceRangeChange = useCallback((min, max) => {
8246
+ setMinPrice(min);
8247
+ setMaxPrice(max);
8248
+ setPage(1);
8249
+ }, []);
8250
+ const key = template ?? "default" /* Default */;
8251
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS[key] ?? DefaultCatalogueLayout;
8252
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
8253
+ Layout,
8254
+ {
8255
+ products,
8256
+ categories,
8257
+ facets,
8258
+ isLoading,
8259
+ selectedCategory,
8260
+ onCategoryChange: handleCategoryChange,
8261
+ searchQuery,
8262
+ onSearchChange: setSearchQuery,
8263
+ sortBy,
8264
+ sortOrder,
8265
+ onSortChange: handleSortChange,
8266
+ inStockOnly,
8267
+ onInStockChange: setInStockOnly,
8268
+ selectedTags,
8269
+ availableTags,
8270
+ onTagToggle: handleTagToggle,
8271
+ minPrice,
8272
+ maxPrice,
8273
+ onPriceRangeChange: handlePriceRangeChange,
8274
+ page,
8275
+ totalPages,
8276
+ onPageChange: setPage,
8277
+ renderCard,
8278
+ renderImage,
8279
+ renderLink,
8280
+ onQuickAdd,
8281
+ onProductClick,
8282
+ title
8283
+ }
8284
+ ) });
8285
+ }
8285
8286
  function TwoColumnGrid({
8286
8287
  left,
8287
8288
  right,
@@ -8910,7 +8911,7 @@ var ProductTemplate = /* @__PURE__ */ ((ProductTemplate2) => {
8910
8911
  ProductTemplate2["Physical"] = "physical";
8911
8912
  return ProductTemplate2;
8912
8913
  })(ProductTemplate || {});
8913
- var BUILT_IN_LAYOUTS = {
8914
+ var BUILT_IN_LAYOUTS2 = {
8914
8915
  ["food" /* Food */]: FoodProductLayout,
8915
8916
  ["wholesale" /* Wholesale */]: WholesaleProductLayout,
8916
8917
  ["service" /* Service */]: ServiceProductLayout,
@@ -8947,8 +8948,8 @@ function resolveLayout(product, pages, templates) {
8947
8948
  if (templates?.[key]) {
8948
8949
  return templates[key];
8949
8950
  }
8950
- if (BUILT_IN_LAYOUTS[key]) {
8951
- return BUILT_IN_LAYOUTS[key];
8951
+ if (BUILT_IN_LAYOUTS2[key]) {
8952
+ return BUILT_IN_LAYOUTS2[key];
8952
8953
  }
8953
8954
  return DefaultProductLayout;
8954
8955
  }
@@ -9006,56 +9007,168 @@ function ProductPage({
9006
9007
  }
9007
9008
  ) });
9008
9009
  }
9009
- function CartPage({
9010
- title = "Your Cart",
9010
+ function DefaultCartLayout({
9011
+ cart,
9011
9012
  onCheckout,
9012
9013
  onContinueShopping,
9013
9014
  onDiscountApply,
9014
9015
  onDiscountClear,
9015
9016
  showDiscount = true,
9016
- showContinueShopping = true,
9017
9017
  checkoutLabel = "Proceed to Checkout",
9018
- className,
9019
- classNames
9018
+ className
9020
9019
  }) {
9021
- const { isEmpty, subtotal } = useCart();
9022
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page": true, className: cn(className, classNames?.root), children: [
9023
- /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page-header": true, className: classNames?.header, children: [
9024
- /* @__PURE__ */ jsx("h1", { "data-cimplify-cart-page-title": true, className: classNames?.title, children: title }),
9025
- showContinueShopping && /* @__PURE__ */ jsx(
9020
+ if (cart.isEmpty) {
9021
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("text-center py-20", className), children: [
9022
+ /* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto text-muted-foreground/30", fill: "none", stroke: "currentColor", strokeWidth: "1", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }),
9023
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium mt-4", children: "Your cart is empty" }),
9024
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Add some items to get started" }),
9025
+ onContinueShopping && /* @__PURE__ */ jsx(
9026
9026
  "button",
9027
9027
  {
9028
- type: "button",
9029
9028
  onClick: onContinueShopping,
9030
- "data-cimplify-cart-continue": true,
9031
- className: classNames?.continueButton,
9032
- children: "Continue Shopping"
9029
+ className: "text-sm font-medium text-primary mt-4 hover:underline",
9030
+ children: "Continue shopping"
9033
9031
  }
9034
9032
  )
9035
- ] }),
9036
- /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page-content": true, className: classNames?.content, children: [
9037
- /* @__PURE__ */ jsx(CartSummary, {}),
9038
- showDiscount && !isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page-discount": true, className: classNames?.discount, children: /* @__PURE__ */ jsx(
9039
- DiscountInput,
9033
+ ] });
9034
+ }
9035
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("space-y-6", className), children: [
9036
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9037
+ /* @__PURE__ */ jsxs("h1", { className: "text-2xl font-bold tracking-tight", children: [
9038
+ "Your Cart (",
9039
+ cart.itemCount,
9040
+ " ",
9041
+ cart.itemCount === 1 ? "item" : "items",
9042
+ ")"
9043
+ ] }),
9044
+ onContinueShopping && /* @__PURE__ */ jsx(
9045
+ "button",
9040
9046
  {
9041
- orderSubtotal: subtotal.toString(),
9042
- onApply: onDiscountApply,
9043
- onClear: onDiscountClear
9047
+ onClick: onContinueShopping,
9048
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
9049
+ children: "Continue shopping"
9044
9050
  }
9045
- ) })
9051
+ )
9052
+ ] }),
9053
+ /* @__PURE__ */ jsxs("div", { className: "grid lg:grid-cols-[1fr_380px] gap-8", children: [
9054
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(CartSummary, {}) }),
9055
+ /* @__PURE__ */ jsx("div", { className: "lg:sticky lg:top-6 h-fit space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "border border-border rounded-[14px] p-6 space-y-4", children: [
9056
+ /* @__PURE__ */ jsx("h2", { className: "font-semibold", children: "Order Summary" }),
9057
+ showDiscount && /* @__PURE__ */ jsx(
9058
+ DiscountInput,
9059
+ {
9060
+ orderSubtotal: cart.subtotal.toString(),
9061
+ onApply: onDiscountApply,
9062
+ onClear: onDiscountClear
9063
+ }
9064
+ ),
9065
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm", children: [
9066
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9067
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
9068
+ /* @__PURE__ */ jsx(Price, { amount: cart.subtotal })
9069
+ ] }),
9070
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9071
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Tax" }),
9072
+ /* @__PURE__ */ jsx(Price, { amount: cart.tax })
9073
+ ] }),
9074
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between font-semibold text-base pt-2 border-t border-border", children: [
9075
+ /* @__PURE__ */ jsx("span", { children: "Total" }),
9076
+ /* @__PURE__ */ jsx(Price, { amount: cart.total })
9077
+ ] })
9078
+ ] }),
9079
+ /* @__PURE__ */ jsx(
9080
+ "button",
9081
+ {
9082
+ onClick: onCheckout,
9083
+ className: "w-full h-12 bg-foreground text-background font-medium text-sm rounded-lg hover:bg-foreground/90 transition-colors",
9084
+ children: checkoutLabel
9085
+ }
9086
+ )
9087
+ ] }) })
9088
+ ] })
9089
+ ] });
9090
+ }
9091
+ function CompactCartLayout({
9092
+ cart,
9093
+ onCheckout,
9094
+ onContinueShopping,
9095
+ checkoutLabel = "Place Order",
9096
+ className
9097
+ }) {
9098
+ if (cart.isEmpty) {
9099
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "compact", className: cn("text-center py-16", className), children: [
9100
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "Your order is empty" }),
9101
+ onContinueShopping && /* @__PURE__ */ jsx("button", { onClick: onContinueShopping, className: "text-sm font-medium text-primary mt-3 hover:underline", children: "Browse menu" })
9102
+ ] });
9103
+ }
9104
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "compact", className: cn("max-w-lg mx-auto space-y-4", className), children: [
9105
+ /* @__PURE__ */ jsxs("h1", { className: "text-xl font-bold tracking-tight", children: [
9106
+ "Your Order (",
9107
+ cart.itemCount,
9108
+ ")"
9109
+ ] }),
9110
+ /* @__PURE__ */ jsx(CartSummary, {}),
9111
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm pt-4 border-t border-border", children: [
9112
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9113
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
9114
+ /* @__PURE__ */ jsx(Price, { amount: cart.subtotal })
9115
+ ] }),
9116
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9117
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Tax" }),
9118
+ /* @__PURE__ */ jsx(Price, { amount: cart.tax })
9119
+ ] }),
9120
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between font-semibold text-base pt-2 border-t border-border", children: [
9121
+ /* @__PURE__ */ jsx("span", { children: "Total" }),
9122
+ /* @__PURE__ */ jsx(Price, { amount: cart.total })
9123
+ ] })
9046
9124
  ] }),
9047
- !isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page-footer": true, className: classNames?.footer, children: /* @__PURE__ */ jsx(
9125
+ /* @__PURE__ */ jsx(
9048
9126
  "button",
9049
9127
  {
9050
- type: "button",
9051
9128
  onClick: onCheckout,
9052
- "data-cimplify-cart-checkout-button": true,
9053
- className: classNames?.checkoutButton,
9129
+ className: "w-full h-12 bg-foreground text-background font-medium text-sm rounded-lg hover:bg-foreground/90 transition-colors",
9054
9130
  children: checkoutLabel
9055
9131
  }
9056
- ) })
9132
+ )
9057
9133
  ] });
9058
9134
  }
9135
+ var CartTemplate = /* @__PURE__ */ ((CartTemplate2) => {
9136
+ CartTemplate2["Default"] = "default";
9137
+ CartTemplate2["Compact"] = "compact";
9138
+ return CartTemplate2;
9139
+ })(CartTemplate || {});
9140
+ var BUILT_IN_LAYOUTS3 = {
9141
+ ["default" /* Default */]: DefaultCartLayout,
9142
+ ["compact" /* Compact */]: CompactCartLayout
9143
+ };
9144
+ function CartPage({
9145
+ template,
9146
+ layouts,
9147
+ onCheckout,
9148
+ onContinueShopping,
9149
+ onDiscountApply,
9150
+ onDiscountClear,
9151
+ showDiscount = true,
9152
+ checkoutLabel,
9153
+ className,
9154
+ classNames
9155
+ }) {
9156
+ const cart = useCart();
9157
+ const key = template ?? "default" /* Default */;
9158
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS3[key] ?? DefaultCartLayout;
9159
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
9160
+ Layout,
9161
+ {
9162
+ cart,
9163
+ onCheckout,
9164
+ onContinueShopping,
9165
+ onDiscountApply,
9166
+ onDiscountClear,
9167
+ showDiscount,
9168
+ checkoutLabel
9169
+ }
9170
+ ) });
9171
+ }
9059
9172
  function CheckoutPage({
9060
9173
  title = "Checkout",
9061
9174
  onComplete,
@@ -9079,22 +9192,362 @@ function CheckoutPage({
9079
9192
  )
9080
9193
  ] });
9081
9194
  }
9195
+ function DefaultCollectionLayout({
9196
+ collection,
9197
+ products,
9198
+ renderCard,
9199
+ renderImage,
9200
+ renderLink,
9201
+ onQuickAdd,
9202
+ className
9203
+ }) {
9204
+ const [searchQuery, setSearchQuery] = useState("");
9205
+ const [activeTag, setActiveTag] = useState(null);
9206
+ const collectionTags = useMemo(() => {
9207
+ const tagSet = /* @__PURE__ */ new Set();
9208
+ for (const p of products) {
9209
+ if (p.tags) {
9210
+ for (const t of p.tags) tagSet.add(t);
9211
+ }
9212
+ }
9213
+ return Array.from(tagSet).slice(0, 6);
9214
+ }, [products]);
9215
+ const filtered = useMemo(() => {
9216
+ let result = products;
9217
+ if (searchQuery.trim().length >= 2) {
9218
+ const q = searchQuery.toLowerCase();
9219
+ result = result.filter(
9220
+ (p) => p.name.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q)
9221
+ );
9222
+ }
9223
+ if (activeTag) {
9224
+ result = result.filter((p) => p.tags?.includes(activeTag));
9225
+ }
9226
+ return result;
9227
+ }, [products, searchQuery, activeTag]);
9228
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "default", className: cn("space-y-8", className), children: [
9229
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-hero": true, className: "relative overflow-hidden rounded-2xl bg-muted", children: [
9230
+ collection.image_url && /* @__PURE__ */ jsx(
9231
+ "img",
9232
+ {
9233
+ src: collection.image_url,
9234
+ alt: collection.name,
9235
+ className: "w-full h-64 lg:h-80 object-cover"
9236
+ }
9237
+ ),
9238
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent" }),
9239
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-6 lg:p-8", children: [
9240
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl lg:text-4xl font-bold text-white tracking-tight", children: collection.name }),
9241
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-white/80 mt-2 max-w-lg text-sm lg:text-base", children: collection.description }),
9242
+ /* @__PURE__ */ jsxs("p", { className: "text-white/60 text-sm mt-2", children: [
9243
+ products.length,
9244
+ " ",
9245
+ products.length === 1 ? "item" : "items"
9246
+ ] })
9247
+ ] })
9248
+ ] }),
9249
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-3", children: [
9250
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0 w-full sm:max-w-xs", children: [
9251
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9252
+ /* @__PURE__ */ jsx(
9253
+ "input",
9254
+ {
9255
+ type: "search",
9256
+ value: searchQuery,
9257
+ onChange: (e) => setSearchQuery(e.target.value),
9258
+ placeholder: `Search ${collection.name}...`,
9259
+ className: "w-full h-10 pl-10 pr-4 text-sm border border-border rounded-lg bg-background outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-colors"
9260
+ }
9261
+ )
9262
+ ] }),
9263
+ collectionTags.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
9264
+ /* @__PURE__ */ jsx(
9265
+ "button",
9266
+ {
9267
+ onClick: () => setActiveTag(null),
9268
+ className: cn(
9269
+ "text-xs font-medium px-3 py-1.5 rounded-full transition-colors",
9270
+ !activeTag ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9271
+ ),
9272
+ children: "All"
9273
+ }
9274
+ ),
9275
+ collectionTags.map((tag) => /* @__PURE__ */ jsx(
9276
+ "button",
9277
+ {
9278
+ onClick: () => setActiveTag(activeTag === tag ? null : tag),
9279
+ className: cn(
9280
+ "text-xs font-medium px-3 py-1.5 rounded-full transition-colors",
9281
+ activeTag === tag ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9282
+ ),
9283
+ children: tag
9284
+ },
9285
+ tag
9286
+ ))
9287
+ ] })
9288
+ ] }),
9289
+ filtered.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
9290
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9291
+ ProductCard,
9292
+ {
9293
+ product,
9294
+ renderImage,
9295
+ renderLink,
9296
+ onQuickAdd
9297
+ },
9298
+ product.id
9299
+ )
9300
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
9301
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No items match your search." }),
9302
+ /* @__PURE__ */ jsx(
9303
+ "button",
9304
+ {
9305
+ onClick: () => {
9306
+ setSearchQuery("");
9307
+ setActiveTag(null);
9308
+ },
9309
+ className: "text-sm font-medium text-primary mt-2 hover:underline",
9310
+ children: "Clear filters"
9311
+ }
9312
+ )
9313
+ ] })
9314
+ ] });
9315
+ }
9316
+ function FeaturedCollectionLayout({
9317
+ collection,
9318
+ products,
9319
+ renderCard,
9320
+ renderImage,
9321
+ renderLink,
9322
+ onQuickAdd,
9323
+ className
9324
+ }) {
9325
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "featured", className: cn("space-y-10", className), children: [
9326
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-hero": true, className: "relative overflow-hidden rounded-2xl bg-muted", children: [
9327
+ collection.image_url && /* @__PURE__ */ jsx(
9328
+ "img",
9329
+ {
9330
+ src: collection.image_url,
9331
+ alt: collection.name,
9332
+ className: "w-full h-72 lg:h-96 object-cover"
9333
+ }
9334
+ ),
9335
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent" }),
9336
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-8 lg:p-12", children: [
9337
+ collection.tags && collection.tags.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-white/70 uppercase tracking-widest", children: collection.tags[0] }),
9338
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl lg:text-5xl font-bold text-white tracking-tight mt-2", children: collection.name }),
9339
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-white/80 mt-3 max-w-2xl text-base lg:text-lg leading-relaxed", children: collection.description })
9340
+ ] })
9341
+ ] }),
9342
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: products.map(
9343
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9344
+ ProductCard,
9345
+ {
9346
+ product,
9347
+ renderImage,
9348
+ renderLink,
9349
+ onQuickAdd
9350
+ },
9351
+ product.id
9352
+ )
9353
+ ) })
9354
+ ] });
9355
+ }
9356
+ function CatalogueCollectionLayout({
9357
+ collection,
9358
+ products,
9359
+ renderCard,
9360
+ renderImage,
9361
+ renderLink,
9362
+ onQuickAdd,
9363
+ className
9364
+ }) {
9365
+ const [searchQuery, setSearchQuery] = useState("");
9366
+ const [activeCategory, setActiveCategory] = useState(null);
9367
+ const [sortBy, setSortBy] = useState("default");
9368
+ const categories = useMemo(() => {
9369
+ const cats = /* @__PURE__ */ new Map();
9370
+ for (const p of products) {
9371
+ if (p.category_id && p.tags) {
9372
+ for (const t of p.tags) {
9373
+ if (!cats.has(t)) cats.set(t, t);
9374
+ }
9375
+ }
9376
+ }
9377
+ return Array.from(cats.values()).slice(0, 8);
9378
+ }, [products]);
9379
+ const filtered = useMemo(() => {
9380
+ let result = products;
9381
+ if (searchQuery.trim().length >= 2) {
9382
+ const q = searchQuery.toLowerCase();
9383
+ result = result.filter(
9384
+ (p) => p.name.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q)
9385
+ );
9386
+ }
9387
+ if (activeCategory) {
9388
+ result = result.filter((p) => p.tags?.includes(activeCategory));
9389
+ }
9390
+ if (sortBy === "price-asc") {
9391
+ result = [...result].sort((a, b) => parsePrice(a.default_price) - parsePrice(b.default_price));
9392
+ } else if (sortBy === "price-desc") {
9393
+ result = [...result].sort((a, b) => parsePrice(b.default_price) - parsePrice(a.default_price));
9394
+ } else if (sortBy === "name") {
9395
+ result = [...result].sort((a, b) => a.name.localeCompare(b.name));
9396
+ }
9397
+ return result;
9398
+ }, [products, searchQuery, activeCategory, sortBy]);
9399
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "catalogue", className: cn("space-y-6", className), children: [
9400
+ /* @__PURE__ */ jsxs("div", { children: [
9401
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl lg:text-3xl font-bold tracking-tight", children: collection.name }),
9402
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 max-w-2xl", children: collection.description })
9403
+ ] }),
9404
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 pb-4 border-b border-border", children: [
9405
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 w-full", children: [
9406
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 max-w-sm", children: [
9407
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9408
+ /* @__PURE__ */ jsx(
9409
+ "input",
9410
+ {
9411
+ type: "search",
9412
+ value: searchQuery,
9413
+ onChange: (e) => setSearchQuery(e.target.value),
9414
+ placeholder: "Search...",
9415
+ className: "w-full h-9 pl-10 pr-4 text-sm border border-border rounded-lg bg-background outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-colors"
9416
+ }
9417
+ )
9418
+ ] }),
9419
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto scrollbar-hide", children: [
9420
+ /* @__PURE__ */ jsx(
9421
+ "button",
9422
+ {
9423
+ onClick: () => setActiveCategory(null),
9424
+ className: cn(
9425
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9426
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9427
+ ),
9428
+ children: "All"
9429
+ }
9430
+ ),
9431
+ categories.map((cat) => /* @__PURE__ */ jsx(
9432
+ "button",
9433
+ {
9434
+ onClick: () => setActiveCategory(activeCategory === cat ? null : cat),
9435
+ className: cn(
9436
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9437
+ activeCategory === cat ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9438
+ ),
9439
+ children: cat
9440
+ },
9441
+ cat
9442
+ ))
9443
+ ] })
9444
+ ] }),
9445
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 shrink-0", children: [
9446
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
9447
+ filtered.length,
9448
+ " items"
9449
+ ] }),
9450
+ /* @__PURE__ */ jsxs(
9451
+ "select",
9452
+ {
9453
+ value: sortBy,
9454
+ onChange: (e) => setSortBy(e.target.value),
9455
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none focus:ring-2 focus:ring-primary/20",
9456
+ children: [
9457
+ /* @__PURE__ */ jsx("option", { value: "default", children: "Sort: Default" }),
9458
+ /* @__PURE__ */ jsx("option", { value: "price-asc", children: "Price: Low to High" }),
9459
+ /* @__PURE__ */ jsx("option", { value: "price-desc", children: "Price: High to Low" }),
9460
+ /* @__PURE__ */ jsx("option", { value: "name", children: "Name: A-Z" })
9461
+ ]
9462
+ }
9463
+ )
9464
+ ] })
9465
+ ] }),
9466
+ filtered.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
9467
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9468
+ ProductCard,
9469
+ {
9470
+ product,
9471
+ renderImage,
9472
+ renderLink,
9473
+ onQuickAdd
9474
+ },
9475
+ product.id
9476
+ )
9477
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
9478
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No products found." }),
9479
+ /* @__PURE__ */ jsx(
9480
+ "button",
9481
+ {
9482
+ onClick: () => {
9483
+ setSearchQuery("");
9484
+ setActiveCategory(null);
9485
+ },
9486
+ className: "text-sm font-medium text-primary mt-2 hover:underline",
9487
+ children: "Clear filters"
9488
+ }
9489
+ )
9490
+ ] })
9491
+ ] });
9492
+ }
9493
+ var CollectionTemplate = /* @__PURE__ */ ((CollectionTemplate2) => {
9494
+ CollectionTemplate2["Default"] = "default";
9495
+ CollectionTemplate2["Featured"] = "featured";
9496
+ CollectionTemplate2["Catalogue"] = "catalogue";
9497
+ return CollectionTemplate2;
9498
+ })(CollectionTemplate || {});
9499
+ var BUILT_IN_LAYOUTS4 = {
9500
+ ["default" /* Default */]: DefaultCollectionLayout,
9501
+ ["featured" /* Featured */]: FeaturedCollectionLayout,
9502
+ ["catalogue" /* Catalogue */]: CatalogueCollectionLayout
9503
+ };
9504
+ var LARGE_COLLECTION_THRESHOLD = 30;
9505
+ function resolveTemplateKey2(collection, productCount) {
9506
+ const metaTemplate = collection.metadata?.page_template;
9507
+ if (typeof metaTemplate === "string" && metaTemplate.trim()) {
9508
+ return metaTemplate.trim();
9509
+ }
9510
+ if (collection.tags?.includes("featured") || collection.metadata?.is_featured === true) {
9511
+ return "featured" /* Featured */;
9512
+ }
9513
+ if (productCount > LARGE_COLLECTION_THRESHOLD) {
9514
+ return "catalogue" /* Catalogue */;
9515
+ }
9516
+ return "default" /* Default */;
9517
+ }
9518
+ function resolveLayout2(collection, productCount, pages, templates) {
9519
+ if (pages?.[collection.slug]) {
9520
+ return pages[collection.slug];
9521
+ }
9522
+ const key = resolveTemplateKey2(collection, productCount);
9523
+ if (templates?.[key]) {
9524
+ return templates[key];
9525
+ }
9526
+ if (BUILT_IN_LAYOUTS4[key]) {
9527
+ return BUILT_IN_LAYOUTS4[key];
9528
+ }
9529
+ return DefaultCollectionLayout;
9530
+ }
9082
9531
  function CollectionPage({
9083
9532
  collectionId,
9084
9533
  collection: collectionProp,
9085
9534
  products: productsProp,
9535
+ pages,
9536
+ templates,
9086
9537
  renderCard,
9087
9538
  renderImage,
9088
- columns,
9539
+ renderLink,
9540
+ onQuickAdd,
9089
9541
  className,
9090
9542
  classNames
9091
9543
  }) {
9544
+ const resolvedId = collectionId || collectionProp?.slug || collectionProp?.id || "";
9092
9545
  const {
9093
9546
  collection: fetchedCollection,
9094
9547
  products: fetchedProducts,
9095
9548
  isLoading
9096
- } = useCollection(collectionProp ? null : collectionId, {
9097
- enabled: !collectionProp
9549
+ } = useCollection(collectionProp ? null : resolvedId, {
9550
+ enabled: !collectionProp && resolvedId.length > 0
9098
9551
  });
9099
9552
  const collection = collectionProp ?? fetchedCollection;
9100
9553
  const products = productsProp ?? fetchedProducts;
@@ -9104,37 +9557,35 @@ function CollectionPage({
9104
9557
  {
9105
9558
  "data-cimplify-collection-page": true,
9106
9559
  "aria-busy": "true",
9107
- className: cn(className, classNames?.root, classNames?.loading)
9560
+ className: cn(className, classNames?.root, classNames?.loading),
9561
+ children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
9562
+ /* @__PURE__ */ jsx("div", { className: "h-64 lg:h-80 bg-muted rounded-2xl" }),
9563
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
9564
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
9565
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
9566
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
9567
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
9568
+ ] })
9569
+ ] }, i)) })
9570
+ ] })
9108
9571
  }
9109
9572
  );
9110
9573
  }
9111
9574
  if (!collection) {
9112
- return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx("p", { children: "Collection not found." }) });
9575
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Collection not found." }) });
9113
9576
  }
9114
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: [
9115
- /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-header": true, className: classNames?.header, children: [
9116
- collection.image_url && /* @__PURE__ */ jsx(
9117
- "img",
9118
- {
9119
- src: collection.image_url,
9120
- alt: collection.name,
9121
- "data-cimplify-collection-image": true,
9122
- className: classNames?.image
9123
- }
9124
- ),
9125
- /* @__PURE__ */ jsx("h1", { "data-cimplify-collection-title": true, className: classNames?.title, children: collection.name }),
9126
- collection.description && /* @__PURE__ */ jsx("p", { "data-cimplify-collection-description": true, className: classNames?.description, children: collection.description })
9127
- ] }),
9128
- /* @__PURE__ */ jsx("div", { "data-cimplify-collection-grid": true, className: classNames?.grid, children: /* @__PURE__ */ jsx(
9129
- ProductGrid,
9130
- {
9131
- products,
9132
- renderCard,
9133
- renderImage,
9134
- columns
9135
- }
9136
- ) })
9137
- ] });
9577
+ const Layout = resolveLayout2(collection, products.length, pages, templates);
9578
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
9579
+ Layout,
9580
+ {
9581
+ collection,
9582
+ products,
9583
+ renderCard,
9584
+ renderImage,
9585
+ renderLink,
9586
+ onQuickAdd
9587
+ }
9588
+ ) });
9138
9589
  }
9139
9590
  function OrderDetailPage({
9140
9591
  orderId,
@@ -9253,573 +9704,355 @@ function OrderHistoryPage({
9253
9704
  ) })
9254
9705
  ] });
9255
9706
  }
9256
- function SearchPage({
9257
- title = "Search",
9258
- placeholder = "What are you looking for?",
9259
- onProductClick,
9707
+ function DefaultSearchLayout({
9708
+ search,
9709
+ facets,
9710
+ categories,
9711
+ activeCategory,
9712
+ onCategoryChange,
9713
+ inStockOnly,
9714
+ onInStockChange,
9715
+ sortBy,
9716
+ onSortChange,
9260
9717
  renderCard,
9261
9718
  renderImage,
9262
- columns,
9263
- className,
9264
- classNames
9719
+ renderLink,
9720
+ onQuickAdd,
9721
+ placeholder = "Search products...",
9722
+ className
9265
9723
  }) {
9266
- const { results, isLoading, query, setQuery, clear } = useSearch();
9267
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page": true, className: cn(className, classNames?.root), children: [
9268
- /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-search-page-title": true, className: classNames?.title, children: title }) }),
9269
- /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page-input": true, className: classNames?.inputContainer, children: [
9724
+ const { query, setQuery, results, isLoading, clear } = search;
9725
+ const hasFacets = facets && facets.length > 0 || categories && categories.length > 0;
9726
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-layout": "default", className: cn("space-y-6", className), children: [
9727
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
9728
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9270
9729
  /* @__PURE__ */ jsx(
9271
- Input,
9730
+ "input",
9272
9731
  {
9273
9732
  type: "search",
9274
9733
  value: query,
9275
9734
  onChange: (e) => setQuery(e.target.value),
9276
9735
  placeholder,
9277
- "data-cimplify-search-page-field": true,
9278
- className: classNames?.input,
9279
- "aria-label": "Search products",
9736
+ className: "w-full h-14 pl-12 pr-12 text-base border border-border rounded-xl bg-background outline-none focus:ring-2 focus:ring-primary/10 focus:border-primary/30 transition-all",
9280
9737
  autoFocus: true
9281
9738
  }
9282
9739
  ),
9283
9740
  query.length > 0 && /* @__PURE__ */ jsx(
9284
9741
  "button",
9285
9742
  {
9286
- type: "button",
9287
9743
  onClick: clear,
9288
- "data-cimplify-search-page-clear": true,
9289
- className: classNames?.clearButton,
9744
+ className: "absolute right-4 top-1/2 -translate-y-1/2 w-6 h-6 flex items-center justify-center text-muted-foreground hover:text-foreground rounded-full hover:bg-muted transition-colors",
9290
9745
  "aria-label": "Clear search",
9291
- children: "\xD7"
9746
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M6 18L18 6M6 6l12 12" }) })
9292
9747
  }
9293
9748
  )
9294
9749
  ] }),
9295
- query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page-count": true, className: classNames?.resultCount, children: [
9296
- results.length,
9297
- " ",
9298
- results.length === 1 ? "result" : "results",
9299
- " for \u201C",
9300
- query,
9301
- "\u201D"
9302
- ] }),
9303
- /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-grid": true, className: classNames?.grid, children: isLoading ? /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-loading": true, "aria-busy": "true", className: classNames?.loading, children: "Searching..." }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsxs("p", { children: [
9304
- "No products found for \u201C",
9305
- query,
9306
- "\u201D"
9307
- ] }) }) : results.length > 0 && /* @__PURE__ */ jsx(
9308
- ProductGrid,
9309
- {
9310
- products: results,
9311
- renderCard,
9312
- renderImage,
9313
- columns
9314
- }
9315
- ) })
9316
- ] });
9317
- }
9318
- function DealsPage({
9319
- title = "Deals & Offers",
9320
- deals: dealsProp,
9321
- productsOnSale: productsOnSaleProp,
9322
- products: productsProp,
9323
- locationId,
9324
- renderImage,
9325
- columns,
9326
- className,
9327
- classNames
9328
- }) {
9329
- const { deals: fetchedDeals, isLoading: dealsLoading } = useDeals({
9330
- locationId,
9331
- enabled: dealsProp === void 0
9332
- });
9333
- const { products: fetchedOnSale, isLoading: productsLoading } = useProductsOnSale({
9334
- enabled: productsOnSaleProp === void 0
9335
- });
9336
- const deals = dealsProp ?? fetchedDeals;
9337
- const onSale = productsOnSaleProp ?? fetchedOnSale;
9338
- const isLoading = dealsLoading || productsLoading;
9339
- const isEmpty = deals.length === 0 && onSale.length === 0;
9340
- if (isLoading && isEmpty) {
9341
- return /* @__PURE__ */ jsx(
9342
- "div",
9343
- {
9344
- "data-cimplify-deals-page": true,
9345
- "aria-busy": "true",
9346
- className: cn(className, classNames?.root, classNames?.loading)
9347
- }
9348
- );
9349
- }
9350
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-page": true, className: cn(className, classNames?.root), children: [
9351
- /* @__PURE__ */ jsx("div", { "data-cimplify-deals-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-deals-title": true, className: classNames?.title, children: title }) }),
9352
- deals.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-banner-section": true, className: classNames?.bannerSection, children: /* @__PURE__ */ jsx(DealBanner, { deals }) }),
9353
- (onSale.length > 0 || productsProp && productsProp.length > 0) && /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-products": true, className: classNames?.productsSection, children: [
9354
- /* @__PURE__ */ jsx("h2", { "data-cimplify-deals-products-title": true, className: classNames?.productsTitle, children: "On Sale Now" }),
9355
- productsProp ? /* @__PURE__ */ jsx(
9356
- ProductGrid,
9750
+ query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9751
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
9752
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: results.length }),
9753
+ " result",
9754
+ results.length !== 1 ? "s" : "",
9755
+ " for ",
9756
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
9757
+ "\u201C",
9758
+ query,
9759
+ "\u201D"
9760
+ ] })
9761
+ ] }),
9762
+ onSortChange && /* @__PURE__ */ jsxs(
9763
+ "select",
9357
9764
  {
9358
- products: productsProp,
9359
- renderImage,
9360
- columns
9765
+ value: sortBy || "relevance",
9766
+ onChange: (e) => onSortChange(e.target.value),
9767
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none focus:ring-2 focus:ring-primary/10",
9768
+ children: [
9769
+ /* @__PURE__ */ jsx("option", { value: "relevance", children: "Relevance" }),
9770
+ /* @__PURE__ */ jsx("option", { value: "price-asc", children: "Price: Low to High" }),
9771
+ /* @__PURE__ */ jsx("option", { value: "price-desc", children: "Price: High to Low" }),
9772
+ /* @__PURE__ */ jsx("option", { value: "name", children: "Name: A-Z" }),
9773
+ /* @__PURE__ */ jsx("option", { value: "newest", children: "Newest" })
9774
+ ]
9361
9775
  }
9362
- ) : /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-list": true, children: onSale.map((dealInfo) => /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-item": true, children: /* @__PURE__ */ jsx(
9363
- SaleBadge,
9776
+ )
9777
+ ] }),
9778
+ categories && categories.length > 0 && onCategoryChange && /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
9779
+ /* @__PURE__ */ jsx(
9780
+ "button",
9364
9781
  {
9365
- product: { id: dealInfo.product_id, name: dealInfo.deal_name },
9366
- dealInfo,
9367
- showOriginalPrice: true
9782
+ onClick: () => onCategoryChange(null),
9783
+ className: cn(
9784
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9785
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9786
+ ),
9787
+ children: "All"
9368
9788
  }
9369
- ) }, `${dealInfo.product_id}-${dealInfo.deal_id}`)) })
9789
+ ),
9790
+ categories.map((cat) => /* @__PURE__ */ jsx(
9791
+ "button",
9792
+ {
9793
+ onClick: () => onCategoryChange(activeCategory === cat.id ? null : cat.id),
9794
+ className: cn(
9795
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9796
+ activeCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9797
+ ),
9798
+ children: cat.name
9799
+ },
9800
+ cat.id
9801
+ ))
9370
9802
  ] }),
9371
- isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsx("p", { children: "No deals available right now. Check back soon!" }) })
9372
- ] });
9373
- }
9374
- var ANY_VALUE2 = "__any__";
9375
- function roomToResource(room) {
9376
- return {
9377
- id: room.id,
9378
- name: room.name,
9379
- capacity: room.capacity,
9380
- floor: room.floor,
9381
- is_available: room.status === "available"
9382
- };
9383
- }
9384
- function ResourcePicker({
9385
- resources,
9386
- selectedResourceId,
9387
- onResourceSelect,
9388
- showAnyOption = true,
9389
- anyLabel = "Any available",
9390
- renderImage,
9391
- className,
9392
- classNames
9393
- }) {
9394
- const groupValue = selectedResourceId === null ? ANY_VALUE2 : selectedResourceId ?? "";
9395
- return /* @__PURE__ */ jsxs(
9396
- RadioGroup,
9397
- {
9398
- "data-cimplify-resource-picker": true,
9399
- className: cn("flex flex-col gap-2", className, classNames?.root),
9400
- value: groupValue,
9401
- onValueChange: (value) => {
9402
- onResourceSelect?.(value === ANY_VALUE2 ? null : value);
9403
- },
9404
- children: [
9405
- showAnyOption && /* @__PURE__ */ jsx(
9406
- Radio.Root,
9407
- {
9408
- value: ANY_VALUE2,
9409
- "data-cimplify-resource-option": true,
9410
- "data-selected": selectedResourceId === null || void 0,
9411
- "data-any": true,
9412
- className: cn(
9413
- "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
9414
- "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
9415
- classNames?.option
9416
- ),
9417
- children: /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: anyLabel })
9418
- }
9419
- ),
9420
- resources.map((resource) => {
9421
- const unavailable = resource.is_available === false;
9422
- return /* @__PURE__ */ jsxs(
9423
- Radio.Root,
9803
+ /* @__PURE__ */ jsxs("div", { className: hasFacets ? "flex gap-6" : "", children: [
9804
+ hasFacets && /* @__PURE__ */ jsxs("aside", { "data-cimplify-search-facets": true, className: "hidden lg:block w-60 shrink-0 space-y-6", children: [
9805
+ onInStockChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9806
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "In stock only" }),
9807
+ /* @__PURE__ */ jsx(
9808
+ "button",
9424
9809
  {
9425
- value: resource.id,
9426
- disabled: unavailable,
9427
- "data-cimplify-resource-option": true,
9428
- "data-selected": selectedResourceId === resource.id || void 0,
9429
- "data-unavailable": unavailable || void 0,
9810
+ onClick: () => onInStockChange(!inStockOnly),
9430
9811
  className: cn(
9431
- "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
9432
- "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
9433
- unavailable && "opacity-50 cursor-not-allowed",
9434
- classNames?.option,
9435
- unavailable ? classNames?.unavailable : void 0
9812
+ "w-10 h-6 rounded-full transition-colors relative",
9813
+ inStockOnly ? "bg-foreground" : "bg-border"
9436
9814
  ),
9437
- children: [
9438
- resource.image_url && (renderImage ? renderImage({
9439
- src: resource.image_url,
9440
- alt: resource.name,
9441
- className: classNames?.image
9442
- }) : /* @__PURE__ */ jsx(
9443
- "img",
9444
- {
9445
- src: resource.image_url,
9446
- alt: resource.name,
9447
- "data-cimplify-resource-image": true,
9448
- className: cn("w-10 h-10 rounded-lg object-cover", classNames?.image)
9449
- }
9450
- )),
9451
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 flex-1 min-w-0", children: [
9452
- /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: resource.name }),
9453
- resource.description && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-description": true, className: cn("text-sm text-muted-foreground truncate", classNames?.description), children: resource.description }),
9454
- /* @__PURE__ */ jsxs("div", { "data-cimplify-resource-meta": true, className: cn("flex items-center gap-2 text-xs text-muted-foreground", classNames?.meta), children: [
9455
- resource.capacity !== void 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-resource-capacity": true, className: classNames?.capacity, children: [
9456
- "Up to ",
9457
- resource.capacity
9458
- ] }),
9459
- resource.floor && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-floor": true, className: classNames?.floor, children: resource.floor })
9460
- ] })
9461
- ] })
9462
- ]
9463
- },
9464
- resource.id
9465
- );
9466
- })
9467
- ]
9468
- }
9469
- );
9470
- }
9471
- var STEP = {
9472
- SELECT_SLOT: "select-slot",
9473
- SELECT_RESOURCE: "select-resource",
9474
- SELECT_STAFF: "select-staff",
9475
- CONFIRM: "confirm"
9476
- };
9477
- function BookingPage({
9478
- service,
9479
- product,
9480
- staff,
9481
- resources,
9482
- participantCount,
9483
- title,
9484
- onBooked,
9485
- onBack,
9486
- existingBooking,
9487
- onRescheduled,
9488
- showPrice = true,
9489
- className,
9490
- classNames
9491
- }) {
9492
- const { addItem } = useCart();
9493
- const { client } = useCimplifyClient();
9494
- const isReschedule = existingBooking !== void 0;
9495
- const [step, setStep] = useState(STEP.SELECT_SLOT);
9496
- const [selectedSlot, setSelectedSlot] = useState(null);
9497
- const [selectedDate, setSelectedDate] = useState(null);
9498
- const [selectedStaffId, setSelectedStaffId] = useState(null);
9499
- const [selectedResourceId, setSelectedResourceId] = useState(null);
9500
- const [isSubmitting, setIsSubmitting] = useState(false);
9501
- const [error, setError] = useState(null);
9502
- const hasResourceStep = resources && resources.length > 0;
9503
- const hasStaffStep = staff && staff.length > 0;
9504
- const depositType = product?.deposit_type;
9505
- const depositAmount = product?.deposit_amount;
9506
- const hasDeposit = depositType !== void 0 && depositType !== "none" && depositAmount !== void 0 && parsePrice(depositAmount) !== 0;
9507
- const cancellationMinutes = product?.cancellation_window_minutes;
9508
- const noShowFee = product?.no_show_fee;
9509
- const handleSlotSelect = useCallback(
9510
- (slot, date) => {
9511
- setSelectedSlot(slot);
9512
- setSelectedDate(date);
9513
- setError(null);
9514
- if (hasResourceStep) {
9515
- setStep(STEP.SELECT_RESOURCE);
9516
- } else if (hasStaffStep) {
9517
- setStep(STEP.SELECT_STAFF);
9518
- } else {
9519
- setStep(STEP.CONFIRM);
9520
- }
9521
- },
9522
- [hasResourceStep, hasStaffStep]
9523
- );
9524
- const handleResourceSelect = useCallback(
9525
- (resourceId) => {
9526
- setSelectedResourceId(resourceId);
9527
- if (hasStaffStep) {
9528
- setStep(STEP.SELECT_STAFF);
9529
- } else {
9530
- setStep(STEP.CONFIRM);
9531
- }
9532
- },
9533
- [hasStaffStep]
9534
- );
9535
- const handleStaffSelect = useCallback((staffId) => {
9536
- setSelectedStaffId(staffId);
9537
- setStep(STEP.CONFIRM);
9538
- }, []);
9539
- const handleBack = useCallback(() => {
9540
- setError(null);
9541
- if (step === STEP.CONFIRM && hasStaffStep) {
9542
- setStep(STEP.SELECT_STAFF);
9543
- } else if (step === STEP.CONFIRM && hasResourceStep) {
9544
- setStep(STEP.SELECT_RESOURCE);
9545
- } else if (step === STEP.SELECT_STAFF && hasResourceStep) {
9546
- setStep(STEP.SELECT_RESOURCE);
9547
- } else if (step === STEP.CONFIRM || step === STEP.SELECT_STAFF || step === STEP.SELECT_RESOURCE) {
9548
- setStep(STEP.SELECT_SLOT);
9549
- } else {
9550
- onBack?.();
9551
- }
9552
- }, [step, hasStaffStep, hasResourceStep, onBack]);
9553
- const handleConfirm = useCallback(async () => {
9554
- if (!selectedSlot || !selectedDate) return;
9555
- setIsSubmitting(true);
9556
- setError(null);
9557
- try {
9558
- if (isReschedule && existingBooking) {
9559
- const serviceItem = existingBooking.service_items[0];
9560
- const result = await client.scheduling.rescheduleBooking({
9561
- order_id: existingBooking.order_id,
9562
- line_item_id: serviceItem?.service_id ?? existingBooking.order_id,
9563
- new_start_time: selectedSlot.start_time,
9564
- new_end_time: selectedSlot.end_time,
9565
- new_staff_id: selectedStaffId || void 0,
9566
- reschedule_type: "customer"
9567
- });
9568
- if (!result.ok) {
9569
- throw result.error;
9570
- }
9571
- onRescheduled?.(existingBooking, selectedSlot);
9572
- } else {
9573
- const serviceProduct = {
9574
- id: service.product_id || service.id,
9575
- business_id: service.business_id || "",
9576
- category_id: service.category_id || void 0,
9577
- name: service.name,
9578
- slug: service.id,
9579
- description: service.description || void 0,
9580
- image_url: service.image_url || void 0,
9581
- default_price: service.price || "0",
9582
- type: "service",
9583
- inventory_type: "none",
9584
- variant_strategy: "fetch_all",
9585
- is_active: service.is_available,
9586
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
9587
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
9588
- };
9589
- await addItem(serviceProduct, 1, {
9590
- scheduledStart: selectedSlot.start_time,
9591
- scheduledEnd: selectedSlot.end_time,
9592
- staffId: selectedStaffId || void 0,
9593
- resourceId: selectedResourceId || void 0
9594
- });
9595
- onBooked?.(selectedSlot, selectedStaffId);
9596
- }
9597
- } catch (err) {
9598
- const fallbackMessage = isReschedule ? "Failed to reschedule booking" : "Failed to add booking to cart";
9599
- setError(err instanceof Error ? err.message : fallbackMessage);
9600
- } finally {
9601
- setIsSubmitting(false);
9602
- }
9603
- }, [selectedSlot, selectedDate, selectedStaffId, service, addItem, onBooked, isReschedule, existingBooking, client, onRescheduled]);
9604
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page": true, className: cn(className, classNames?.root), children: [
9605
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page-header": true, className: classNames?.header, children: [
9606
- onBack && step === STEP.SELECT_SLOT && /* @__PURE__ */ jsx(
9607
- "button",
9815
+ children: /* @__PURE__ */ jsx("span", { className: cn(
9816
+ "absolute top-1 w-4 h-4 rounded-full bg-background transition-transform shadow-sm",
9817
+ inStockOnly ? "left-5" : "left-1"
9818
+ ) })
9819
+ }
9820
+ )
9821
+ ] }),
9822
+ facets?.map((facet) => /* @__PURE__ */ jsxs("div", { children: [
9823
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: facet.name }),
9824
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: facet.values.slice(0, 8).map((fv) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
9825
+ /* @__PURE__ */ jsx("input", { type: "checkbox", className: "w-3.5 h-3.5 accent-foreground rounded" }),
9826
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors flex-1", children: fv.value }),
9827
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60", children: fv.count })
9828
+ ] }, fv.value)) })
9829
+ ] }, facet.slug))
9830
+ ] }),
9831
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4 animate-pulse", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
9832
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
9833
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
9834
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
9835
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
9836
+ ] })
9837
+ ] }, i)) }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-20", children: [
9838
+ /* @__PURE__ */ jsx("svg", { className: "w-12 h-12 mx-auto text-muted-foreground/30", fill: "none", stroke: "currentColor", strokeWidth: "1", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9839
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-medium mt-4", children: [
9840
+ "No results for \u201C",
9841
+ query,
9842
+ "\u201D"
9843
+ ] }),
9844
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
9845
+ /* @__PURE__ */ jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
9846
+ ] }) : results.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: results.map(
9847
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9848
+ ProductCard,
9849
+ {
9850
+ product,
9851
+ renderImage,
9852
+ renderLink,
9853
+ onQuickAdd
9854
+ },
9855
+ product.id
9856
+ )
9857
+ ) }) : null })
9858
+ ] })
9859
+ ] });
9860
+ }
9861
+ function CompactSearchLayout({
9862
+ search,
9863
+ categories,
9864
+ activeCategory,
9865
+ onCategoryChange,
9866
+ renderCard,
9867
+ renderImage,
9868
+ renderLink,
9869
+ onQuickAdd,
9870
+ placeholder = "Search menu...",
9871
+ className
9872
+ }) {
9873
+ const { query, setQuery, results, isLoading, clear } = search;
9874
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-layout": "compact", className: cn("space-y-6", className), children: [
9875
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
9876
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9877
+ /* @__PURE__ */ jsx(
9878
+ "input",
9608
9879
  {
9609
- type: "button",
9610
- onClick: onBack,
9611
- "data-cimplify-booking-page-back": true,
9612
- className: classNames?.backButton,
9613
- children: "Back"
9880
+ type: "search",
9881
+ value: query,
9882
+ onChange: (e) => setQuery(e.target.value),
9883
+ placeholder,
9884
+ className: "w-full h-12 pl-12 pr-12 text-base border border-border rounded-xl bg-background outline-none focus:ring-2 focus:ring-primary/10 focus:border-primary/30 transition-all",
9885
+ autoFocus: true
9614
9886
  }
9615
9887
  ),
9616
- step !== STEP.SELECT_SLOT && /* @__PURE__ */ jsx(
9888
+ query.length > 0 && /* @__PURE__ */ jsx(
9617
9889
  "button",
9618
9890
  {
9619
- type: "button",
9620
- onClick: handleBack,
9621
- "data-cimplify-booking-page-back": true,
9622
- className: classNames?.backButton,
9623
- children: "Back"
9624
- }
9625
- ),
9626
- /* @__PURE__ */ jsx("h1", { "data-cimplify-booking-page-title": true, className: classNames?.title, children: title || (isReschedule ? "Reschedule Booking" : `Book ${service.name}`) })
9627
- ] }),
9628
- isReschedule && existingBooking && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-reschedule-info": true, className: classNames?.rescheduleInfo, children: /* @__PURE__ */ jsxs("span", { children: [
9629
- "Rescheduling booking from ",
9630
- new Date(existingBooking.service_items[0]?.scheduled_start ?? existingBooking.created_at).toLocaleDateString()
9631
- ] }) }),
9632
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-service-info": true, className: classNames?.serviceInfo, children: [
9633
- /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-name": true, children: service.name }),
9634
- /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-duration": true, children: formatDuration4(service.duration_minutes, service.duration_unit) }),
9635
- service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-price": true, children: /* @__PURE__ */ jsx(Price, { amount: service.price }) }),
9636
- hasDeposit && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-deposit-info": true, className: classNames?.depositInfo, children: [
9637
- "Deposit: ",
9638
- depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount })
9639
- ] }),
9640
- cancellationMinutes !== void 0 && cancellationMinutes > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-cancellation-policy": true, className: classNames?.cancellationPolicy, children: [
9641
- "Free cancellation up to ",
9642
- cancellationMinutes >= 60 ? `${Math.floor(cancellationMinutes / 60)} hour${Math.floor(cancellationMinutes / 60) !== 1 ? "s" : ""}` : `${cancellationMinutes} minute${cancellationMinutes !== 1 ? "s" : ""}`,
9643
- " before"
9644
- ] }),
9645
- noShowFee !== void 0 && parsePrice(noShowFee) !== 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-no-show-fee": true, className: classNames?.cancellationPolicy, children: [
9646
- "No-show fee: ",
9647
- /* @__PURE__ */ jsx(Price, { amount: noShowFee })
9648
- ] })
9649
- ] }),
9650
- error && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-error": true, className: classNames?.error, children: error }),
9651
- step === STEP.SELECT_SLOT && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-slot", className: classNames?.step, children: [
9652
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Select a date & time" }),
9653
- /* @__PURE__ */ jsx(
9654
- DateSlotPicker,
9655
- {
9656
- serviceId: service.id,
9657
- participantCount,
9658
- selectedSlot,
9659
- onSlotSelect: handleSlotSelect,
9660
- showPrice
9891
+ onClick: clear,
9892
+ className: "absolute right-4 top-1/2 -translate-y-1/2 w-6 h-6 flex items-center justify-center text-muted-foreground hover:text-foreground rounded-full hover:bg-muted transition-colors",
9893
+ "aria-label": "Clear search",
9894
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M6 18L18 6M6 6l12 12" }) })
9661
9895
  }
9662
9896
  )
9663
9897
  ] }),
9664
- step === STEP.SELECT_RESOURCE && resources && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-resource", className: cn(classNames?.step, classNames?.resourceStep), children: [
9665
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Choose a room" }),
9898
+ categories && categories.length > 0 && onCategoryChange && /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
9666
9899
  /* @__PURE__ */ jsx(
9667
- ResourcePicker,
9900
+ "button",
9668
9901
  {
9669
- resources,
9670
- selectedResourceId,
9671
- onResourceSelect: handleResourceSelect
9902
+ onClick: () => onCategoryChange(null),
9903
+ className: cn(
9904
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9905
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9906
+ ),
9907
+ children: "All"
9672
9908
  }
9673
- )
9674
- ] }),
9675
- step === STEP.SELECT_STAFF && staff && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-staff", className: classNames?.step, children: [
9676
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Choose a provider" }),
9677
- /* @__PURE__ */ jsx(
9678
- StaffPicker,
9909
+ ),
9910
+ categories.map((cat) => /* @__PURE__ */ jsx(
9911
+ "button",
9679
9912
  {
9680
- staff,
9681
- selectedStaffId,
9682
- onStaffSelect: handleStaffSelect
9683
- }
9684
- )
9913
+ onClick: () => onCategoryChange(activeCategory === cat.id ? null : cat.id),
9914
+ className: cn(
9915
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9916
+ activeCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9917
+ ),
9918
+ children: cat.name
9919
+ },
9920
+ cat.id
9921
+ ))
9685
9922
  ] }),
9686
- step === STEP.CONFIRM && selectedSlot && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "confirm", className: classNames?.step, children: [
9687
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Confirm your booking" }),
9688
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary": true, className: classNames?.summary, children: [
9689
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9690
- /* @__PURE__ */ jsx("span", { children: "Service" }),
9691
- /* @__PURE__ */ jsx("span", { children: service.name })
9692
- ] }),
9693
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9694
- /* @__PURE__ */ jsx("span", { children: "Date" }),
9695
- /* @__PURE__ */ jsx("span", { children: selectedDate })
9696
- ] }),
9697
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9698
- /* @__PURE__ */ jsx("span", { children: "Time" }),
9699
- /* @__PURE__ */ jsx("span", { children: new Date(selectedSlot.start_time).toLocaleTimeString(void 0, {
9700
- hour: "numeric",
9701
- minute: "2-digit"
9702
- }) })
9703
- ] }),
9704
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9705
- /* @__PURE__ */ jsx("span", { children: "Duration" }),
9706
- /* @__PURE__ */ jsx("span", { children: formatDuration4(service.duration_minutes, service.duration_unit) })
9707
- ] }),
9708
- selectedResourceId && resources && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9709
- /* @__PURE__ */ jsx("span", { children: "Room" }),
9710
- /* @__PURE__ */ jsx("span", { children: resources.find((r) => r.id === selectedResourceId)?.name ?? "Selected" })
9711
- ] }),
9712
- selectedStaffId && staff && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9713
- /* @__PURE__ */ jsx("span", { children: "Provider" }),
9714
- /* @__PURE__ */ jsx("span", { children: staff.find((s) => s.id === selectedStaffId)?.name ?? "Selected" })
9715
- ] }),
9716
- (selectedSlot.price || service.price) && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9717
- /* @__PURE__ */ jsx("span", { children: "Price" }),
9718
- /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(Price, { amount: selectedSlot.price || service.price }) })
9719
- ] }),
9720
- hasDeposit && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: cn(classNames?.summaryRow, classNames?.depositInfo), children: [
9721
- /* @__PURE__ */ jsx("span", { children: "Deposit" }),
9722
- /* @__PURE__ */ jsx("span", { children: depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount }) })
9723
- ] })
9923
+ query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
9924
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: results.length }),
9925
+ " result",
9926
+ results.length !== 1 ? "s" : "",
9927
+ " for ",
9928
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
9929
+ "\u201C",
9930
+ query,
9931
+ "\u201D"
9932
+ ] })
9933
+ ] }),
9934
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-5 animate-pulse", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
9935
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
9936
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
9937
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
9938
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
9939
+ ] })
9940
+ ] }, i)) }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
9941
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-medium", children: [
9942
+ "No results for \u201C",
9943
+ query,
9944
+ "\u201D"
9724
9945
  ] }),
9725
- /* @__PURE__ */ jsx(
9726
- "button",
9946
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
9947
+ /* @__PURE__ */ jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
9948
+ ] }) : results.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: results.map(
9949
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9950
+ ProductCard,
9727
9951
  {
9728
- type: "button",
9729
- onClick: handleConfirm,
9730
- disabled: isSubmitting,
9731
- "data-cimplify-booking-confirm": true,
9732
- className: classNames?.confirmButton,
9733
- children: isSubmitting ? isReschedule ? "Rescheduling\u2026" : "Adding to cart\u2026" : isReschedule ? "Reschedule" : "Confirm Booking"
9734
- }
9952
+ product,
9953
+ renderImage,
9954
+ renderLink,
9955
+ onQuickAdd
9956
+ },
9957
+ product.id
9735
9958
  )
9736
- ] })
9959
+ ) }) : null
9737
9960
  ] });
9738
9961
  }
9739
- var BOOKING_FILTERS = [
9740
- { label: "All", value: "all" },
9741
- { label: "Upcoming", value: "upcoming" },
9742
- { label: "Past", value: "past" }
9743
- ];
9744
- function BookingsPage({
9745
- title = "My Bookings",
9746
- bookings: bookingsProp,
9747
- onBookingNavigate,
9748
- onCancel,
9749
- onReschedule,
9750
- showFilters = true,
9751
- renderBooking,
9962
+ var SearchTemplate = /* @__PURE__ */ ((SearchTemplate2) => {
9963
+ SearchTemplate2["Default"] = "default";
9964
+ SearchTemplate2["Compact"] = "compact";
9965
+ return SearchTemplate2;
9966
+ })(SearchTemplate || {});
9967
+ var BUILT_IN_LAYOUTS5 = {
9968
+ ["default" /* Default */]: DefaultSearchLayout,
9969
+ ["compact" /* Compact */]: CompactSearchLayout
9970
+ };
9971
+ function SearchPage({
9972
+ template,
9973
+ layouts,
9974
+ categories,
9975
+ facets,
9976
+ searchOptions,
9977
+ placeholder,
9978
+ renderCard,
9979
+ renderImage,
9980
+ renderLink,
9981
+ onQuickAdd,
9752
9982
  className,
9753
9983
  classNames
9754
9984
  }) {
9755
- const [filter, setFilter] = useState("all");
9756
- const [selectedBooking, setSelectedBooking] = useState(null);
9757
- const handleBookingClick = useCallback(
9758
- (booking) => {
9759
- if (onBookingNavigate) {
9760
- onBookingNavigate(booking);
9761
- } else {
9762
- setSelectedBooking(booking);
9985
+ const search = useSearch(searchOptions);
9986
+ const key = template ?? "default" /* Default */;
9987
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS5[key] ?? DefaultSearchLayout;
9988
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-search-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
9989
+ Layout,
9990
+ {
9991
+ search,
9992
+ facets,
9993
+ categories,
9994
+ renderCard,
9995
+ renderImage,
9996
+ renderLink,
9997
+ onQuickAdd,
9998
+ placeholder
9999
+ }
10000
+ ) });
10001
+ }
10002
+ function DealsPage({
10003
+ title = "Deals & Offers",
10004
+ deals: dealsProp,
10005
+ productsOnSale: productsOnSaleProp,
10006
+ products: productsProp,
10007
+ locationId,
10008
+ renderImage,
10009
+ columns,
10010
+ className,
10011
+ classNames
10012
+ }) {
10013
+ const { deals: fetchedDeals, isLoading: dealsLoading } = useDeals({
10014
+ locationId,
10015
+ enabled: dealsProp === void 0
10016
+ });
10017
+ const { products: fetchedOnSale, isLoading: productsLoading } = useProductsOnSale({
10018
+ enabled: productsOnSaleProp === void 0
10019
+ });
10020
+ const deals = dealsProp ?? fetchedDeals;
10021
+ const onSale = productsOnSaleProp ?? fetchedOnSale;
10022
+ const isLoading = dealsLoading || productsLoading;
10023
+ const isEmpty = deals.length === 0 && onSale.length === 0;
10024
+ if (isLoading && isEmpty) {
10025
+ return /* @__PURE__ */ jsx(
10026
+ "div",
10027
+ {
10028
+ "data-cimplify-deals-page": true,
10029
+ "aria-busy": "true",
10030
+ className: cn(className, classNames?.root, classNames?.loading)
9763
10031
  }
9764
- },
9765
- [onBookingNavigate]
9766
- );
9767
- const handleBack = useCallback(() => {
9768
- setSelectedBooking(null);
9769
- }, []);
9770
- if (selectedBooking && !onBookingNavigate) {
9771
- return /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsxs("div", { "data-cimplify-bookings-detail": true, className: classNames?.detail, children: [
9772
- /* @__PURE__ */ jsx(
9773
- "button",
10032
+ );
10033
+ }
10034
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-page": true, className: cn(className, classNames?.root), children: [
10035
+ /* @__PURE__ */ jsx("div", { "data-cimplify-deals-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-deals-title": true, className: classNames?.title, children: title }) }),
10036
+ deals.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-banner-section": true, className: classNames?.bannerSection, children: /* @__PURE__ */ jsx(DealBanner, { deals }) }),
10037
+ (onSale.length > 0 || productsProp && productsProp.length > 0) && /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-products": true, className: classNames?.productsSection, children: [
10038
+ /* @__PURE__ */ jsx("h2", { "data-cimplify-deals-products-title": true, className: classNames?.productsTitle, children: "On Sale Now" }),
10039
+ productsProp ? /* @__PURE__ */ jsx(
10040
+ ProductGrid,
9774
10041
  {
9775
- type: "button",
9776
- onClick: handleBack,
9777
- "data-cimplify-bookings-back": true,
9778
- className: classNames?.backButton,
9779
- children: "Back to bookings"
10042
+ products: productsProp,
10043
+ renderImage,
10044
+ columns
9780
10045
  }
9781
- ),
9782
- /* @__PURE__ */ jsx(
9783
- BookingCard,
10046
+ ) : /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-list": true, children: onSale.map((dealInfo) => /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-item": true, children: /* @__PURE__ */ jsx(
10047
+ SaleBadge,
9784
10048
  {
9785
- booking: selectedBooking,
9786
- onCancel,
9787
- onReschedule
10049
+ product: { id: dealInfo.product_id, name: dealInfo.deal_name },
10050
+ dealInfo,
10051
+ showOriginalPrice: true
9788
10052
  }
9789
- )
9790
- ] }) });
9791
- }
9792
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-bookings-page": true, className: cn(className, classNames?.root), children: [
9793
- /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-bookings-title": true, className: classNames?.title, children: title }) }),
9794
- showFilters && /* @__PURE__ */ jsx(
9795
- Tabs.Root,
9796
- {
9797
- value: filter,
9798
- onValueChange: (value) => setFilter(value),
9799
- children: /* @__PURE__ */ jsx(Tabs.List, { "data-cimplify-bookings-filters": true, className: classNames?.filters, children: BOOKING_FILTERS.map((f) => /* @__PURE__ */ jsx(
9800
- Tabs.Tab,
9801
- {
9802
- value: f.value,
9803
- "data-cimplify-booking-filter": true,
9804
- "data-selected": filter === f.value || void 0,
9805
- className: classNames?.filterButton,
9806
- children: f.label
9807
- },
9808
- f.value
9809
- )) })
9810
- }
9811
- ),
9812
- /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-list": true, className: classNames?.list, children: /* @__PURE__ */ jsx(
9813
- BookingList,
9814
- {
9815
- bookings: bookingsProp,
9816
- filter,
9817
- onCancel,
9818
- onReschedule,
9819
- onBookingClick: handleBookingClick,
9820
- renderBooking
9821
- }
9822
- ) })
10053
+ ) }, `${dealInfo.product_id}-${dealInfo.deal_id}`)) })
10054
+ ] }),
10055
+ isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsx("p", { children: "No deals available right now. Check back soon!" }) })
9823
10056
  ] });
9824
10057
  }
9825
10058
  function LocationPicker({
@@ -10180,5 +10413,102 @@ function CurrencySelector({
10180
10413
  );
10181
10414
  }) });
10182
10415
  }
10416
+ var ANY_VALUE2 = "__any__";
10417
+ function roomToResource(room) {
10418
+ return {
10419
+ id: room.id,
10420
+ name: room.name,
10421
+ capacity: room.capacity,
10422
+ floor: room.floor,
10423
+ is_available: room.status === "available"
10424
+ };
10425
+ }
10426
+ function ResourcePicker({
10427
+ resources,
10428
+ selectedResourceId,
10429
+ onResourceSelect,
10430
+ showAnyOption = true,
10431
+ anyLabel = "Any available",
10432
+ renderImage,
10433
+ className,
10434
+ classNames
10435
+ }) {
10436
+ const groupValue = selectedResourceId === null ? ANY_VALUE2 : selectedResourceId ?? "";
10437
+ return /* @__PURE__ */ jsxs(
10438
+ RadioGroup,
10439
+ {
10440
+ "data-cimplify-resource-picker": true,
10441
+ className: cn("flex flex-col gap-2", className, classNames?.root),
10442
+ value: groupValue,
10443
+ onValueChange: (value) => {
10444
+ onResourceSelect?.(value === ANY_VALUE2 ? null : value);
10445
+ },
10446
+ children: [
10447
+ showAnyOption && /* @__PURE__ */ jsx(
10448
+ Radio.Root,
10449
+ {
10450
+ value: ANY_VALUE2,
10451
+ "data-cimplify-resource-option": true,
10452
+ "data-selected": selectedResourceId === null || void 0,
10453
+ "data-any": true,
10454
+ className: cn(
10455
+ "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
10456
+ "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
10457
+ classNames?.option
10458
+ ),
10459
+ children: /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: anyLabel })
10460
+ }
10461
+ ),
10462
+ resources.map((resource) => {
10463
+ const unavailable = resource.is_available === false;
10464
+ return /* @__PURE__ */ jsxs(
10465
+ Radio.Root,
10466
+ {
10467
+ value: resource.id,
10468
+ disabled: unavailable,
10469
+ "data-cimplify-resource-option": true,
10470
+ "data-selected": selectedResourceId === resource.id || void 0,
10471
+ "data-unavailable": unavailable || void 0,
10472
+ className: cn(
10473
+ "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
10474
+ "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
10475
+ unavailable && "opacity-50 cursor-not-allowed",
10476
+ classNames?.option,
10477
+ unavailable ? classNames?.unavailable : void 0
10478
+ ),
10479
+ children: [
10480
+ resource.image_url && (renderImage ? renderImage({
10481
+ src: resource.image_url,
10482
+ alt: resource.name,
10483
+ className: classNames?.image
10484
+ }) : /* @__PURE__ */ jsx(
10485
+ "img",
10486
+ {
10487
+ src: resource.image_url,
10488
+ alt: resource.name,
10489
+ "data-cimplify-resource-image": true,
10490
+ className: cn("w-10 h-10 rounded-lg object-cover", classNames?.image)
10491
+ }
10492
+ )),
10493
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 flex-1 min-w-0", children: [
10494
+ /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: resource.name }),
10495
+ resource.description && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-description": true, className: cn("text-sm text-muted-foreground truncate", classNames?.description), children: resource.description }),
10496
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-resource-meta": true, className: cn("flex items-center gap-2 text-xs text-muted-foreground", classNames?.meta), children: [
10497
+ resource.capacity !== void 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-resource-capacity": true, className: classNames?.capacity, children: [
10498
+ "Up to ",
10499
+ resource.capacity
10500
+ ] }),
10501
+ resource.floor && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-floor": true, className: classNames?.floor, children: resource.floor })
10502
+ ] })
10503
+ ] })
10504
+ ]
10505
+ },
10506
+ resource.id
10507
+ );
10508
+ })
10509
+ ]
10510
+ }
10511
+ );
10512
+ }
10183
10513
 
10184
- export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleSelector, CardImage, CardShell, CardVariant, CartPage, CartSummary, CataloguePage, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyCheckout, CimplifyProvider, CollectionPage, CompactServiceCard, CompositeSelector, CurrencySelector, CustomAttributesTable, DateSlotPicker, DealBanner, DealsPage, DefaultProductLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, ServiceCard, ServiceGrid, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
10514
+ export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BundleSelector, CardImage, CardShell, CardVariant, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeSelector, CurrencySelector, CustomAttributesTable, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };