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