@cimplify/sdk 0.25.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  "use client";
2
- import { DURATION_UNIT, getVariantDisplayName, PRODUCT_TYPE, createCimplifyClient, RENDER_HINT } from './chunk-JMNMSVDQ.mjs';
3
- export { getVariantDisplayName } from './chunk-JMNMSVDQ.mjs';
4
- import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-TBZLJPM4.mjs';
2
+ import { DURATION_UNIT, getVariantDisplayName, PRODUCT_TYPE, createCimplifyClient, RENDER_HINT } from './chunk-MISITC47.mjs';
3
+ export { getVariantDisplayName } from './chunk-MISITC47.mjs';
4
+ import { ELEMENT_TYPES, EVENT_TYPES } from './chunk-3J4PPSMI.mjs';
5
5
  import { isSupportedCurrency, formatPrice, parsePrice, getUnitPriceAtQuantity, isOnSale, getDiscountPercentage, getBasePrice, getPriceRange, formatPriceRange } from './chunk-E3HC2YAE.mjs';
6
6
  import React3, { createContext, useRef, useState, useCallback, useEffect, useContext, useMemo, useSyncExternalStore, useId } from 'react';
7
7
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
- import { NumberField } from '@base-ui/react/number-field';
9
8
  import { clsx } from 'clsx';
10
9
  import { twMerge } from 'tailwind-merge';
10
+ import { NumberField } from '@base-ui/react/number-field';
11
11
  import { RadioGroup } from '@base-ui/react/radio-group';
12
12
  import { Radio } from '@base-ui/react/radio';
13
13
  import { Checkbox } from '@base-ui/react/checkbox';
@@ -1697,6 +1697,101 @@ function CimplifyCheckout({
1697
1697
  errorMessage && /* @__PURE__ */ jsx("p", { "data-cimplify-error": "", style: { marginTop: SPACE.sm, fontSize: 13, color: colors.error }, children: errorMessage })
1698
1698
  ] });
1699
1699
  }
1700
+ function cn(...inputs) {
1701
+ return twMerge(clsx(inputs));
1702
+ }
1703
+ var DEFAULT_LINK_URL = "https://link.cimplify.io";
1704
+ function CimplifyAccount({
1705
+ client: clientProp,
1706
+ linkUrl,
1707
+ section,
1708
+ appearance,
1709
+ onLogout,
1710
+ className
1711
+ }) {
1712
+ const context = useOptionalCimplify();
1713
+ const client = clientProp ?? context?.client;
1714
+ const resolvedLinkUrl = linkUrl || DEFAULT_LINK_URL;
1715
+ const iframeRef = useRef(null);
1716
+ const [height, setHeight] = useState(400);
1717
+ const [isReady, setIsReady] = useState(false);
1718
+ const iframeSrc = useMemo(() => {
1719
+ const path = section ? `/elements/account/${section}` : "/elements/account";
1720
+ const url = new URL(path, resolvedLinkUrl);
1721
+ if (client) {
1722
+ const businessId = client.getBusinessId?.() ?? "";
1723
+ if (businessId) url.searchParams.set("businessId", businessId);
1724
+ }
1725
+ return url.toString();
1726
+ }, [resolvedLinkUrl, section, client]);
1727
+ useEffect(() => {
1728
+ function handleMessage(event) {
1729
+ if (!event.data || typeof event.data !== "object") return;
1730
+ if (iframeRef.current?.contentWindow && event.source !== iframeRef.current.contentWindow) {
1731
+ return;
1732
+ }
1733
+ switch (event.data.type) {
1734
+ case "ready":
1735
+ setIsReady(true);
1736
+ if (typeof event.data.height === "number") {
1737
+ setHeight(event.data.height);
1738
+ }
1739
+ sendInit();
1740
+ break;
1741
+ case "height_change":
1742
+ if (typeof event.data.height === "number") {
1743
+ setHeight(event.data.height);
1744
+ }
1745
+ break;
1746
+ case "logout_complete":
1747
+ onLogout?.();
1748
+ break;
1749
+ }
1750
+ }
1751
+ window.addEventListener("message", handleMessage);
1752
+ return () => window.removeEventListener("message", handleMessage);
1753
+ }, [appearance, client, onLogout]);
1754
+ function sendInit() {
1755
+ const contentWindow = iframeRef.current?.contentWindow;
1756
+ if (!contentWindow) return;
1757
+ const token = client?.getAccessToken?.();
1758
+ contentWindow.postMessage(
1759
+ {
1760
+ type: "init",
1761
+ token: token ?? void 0,
1762
+ appearance: appearance ?? void 0
1763
+ },
1764
+ resolvedLinkUrl
1765
+ );
1766
+ }
1767
+ return /* @__PURE__ */ jsxs(
1768
+ "div",
1769
+ {
1770
+ "data-cimplify-account": true,
1771
+ className: cn("relative overflow-hidden", className),
1772
+ children: [
1773
+ !isReady && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx("div", { className: "w-6 h-6 border-2 border-border border-t-foreground rounded-full animate-spin" }) }),
1774
+ /* @__PURE__ */ jsx(
1775
+ "iframe",
1776
+ {
1777
+ ref: iframeRef,
1778
+ src: iframeSrc,
1779
+ style: {
1780
+ border: "none",
1781
+ width: "100%",
1782
+ height: `${height}px`,
1783
+ display: isReady ? "block" : "none",
1784
+ overflow: "hidden",
1785
+ background: "transparent"
1786
+ },
1787
+ allow: "geolocation",
1788
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
1789
+ }
1790
+ )
1791
+ ]
1792
+ }
1793
+ );
1794
+ }
1700
1795
  function Price({ amount, currency, className, prefix }) {
1701
1796
  const context = useOptionalCimplify();
1702
1797
  const resolvedCurrency = currency ?? context?.displayCurrency ?? "USD";
@@ -3341,9 +3436,6 @@ function useCheckout() {
3341
3436
  );
3342
3437
  return { submit, process, isLoading };
3343
3438
  }
3344
- function cn(...inputs) {
3345
- return twMerge(clsx(inputs));
3346
- }
3347
3439
  function QuantitySelector({
3348
3440
  value,
3349
3441
  onChange,
@@ -7871,226 +7963,346 @@ function BookingList({
7871
7963
  booking.order_id
7872
7964
  )) });
7873
7965
  }
7874
-
7875
- // src/react/utils/format-duration.ts
7876
- var UNIT_LABELS3 = {
7877
- minutes: { singular: "min", plural: "min" },
7878
- hours: { singular: "hr", plural: "hrs" },
7879
- days: { singular: "day", plural: "days" },
7880
- nights: { singular: "night", plural: "nights" },
7881
- weeks: { singular: "week", plural: "weeks" },
7882
- months: { singular: "month", plural: "months" },
7883
- years: { singular: "year", plural: "years" }
7884
- };
7885
- function formatDuration4(value, unit) {
7886
- const resolved = unit ?? "minutes";
7887
- const labels = UNIT_LABELS3[resolved];
7888
- const label = value === 1 ? labels.singular : labels.plural;
7889
- return `${value} ${label}`;
7890
- }
7891
- var ASPECT_STYLES3 = {
7892
- square: { aspectRatio: "1/1" },
7893
- "4/3": { aspectRatio: "4/3" },
7894
- "16/10": { aspectRatio: "16/10" },
7895
- "3/4": { aspectRatio: "3/4" }
7896
- };
7897
- function ServiceCard({
7898
- service,
7899
- onBook,
7900
- href,
7901
- actionLabel = "Book",
7966
+ function DefaultCatalogueLayout({
7967
+ products,
7968
+ categories,
7969
+ facets,
7970
+ isLoading,
7971
+ selectedCategory,
7972
+ onCategoryChange,
7973
+ searchQuery,
7974
+ onSearchChange,
7975
+ sortBy,
7976
+ sortOrder,
7977
+ onSortChange,
7978
+ inStockOnly,
7979
+ onInStockChange,
7980
+ selectedTags,
7981
+ availableTags,
7982
+ onTagToggle,
7983
+ minPrice,
7984
+ maxPrice,
7985
+ onPriceRangeChange,
7986
+ page,
7987
+ totalPages,
7988
+ onPageChange,
7989
+ renderCard,
7902
7990
  renderImage,
7903
- children,
7904
- aspectRatio = "4/3",
7905
- className,
7906
- classNames
7991
+ renderLink,
7992
+ onQuickAdd,
7993
+ title = "Products",
7994
+ className
7907
7995
  }) {
7908
- const imageUrl = service.image_url;
7909
- const cardBody = children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
7910
- imageUrl && /* @__PURE__ */ jsx(
7911
- "div",
7912
- {
7913
- "data-cimplify-service-card-image-container": true,
7914
- className: cn("overflow-hidden rounded-t-xl", classNames?.imageContainer),
7915
- style: ASPECT_STYLES3[aspectRatio],
7916
- children: renderImage ? renderImage({
7917
- src: imageUrl,
7918
- alt: service.name,
7919
- className: classNames?.image
7920
- }) : /* @__PURE__ */ jsx(
7921
- "img",
7996
+ const hasSidebar = facets && facets.length > 0 || availableTags && availableTags.length > 0;
7997
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-layout": "default", className: cn("space-y-6", className), children: [
7998
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4", children: [
7999
+ /* @__PURE__ */ jsxs("div", { children: [
8000
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
8001
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mt-0.5", children: [
8002
+ products.length,
8003
+ " items"
8004
+ ] })
8005
+ ] }),
8006
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full sm:max-w-xs", children: [
8007
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
8008
+ /* @__PURE__ */ jsx(
8009
+ "input",
7922
8010
  {
7923
- src: imageUrl,
7924
- alt: service.name,
7925
- className: cn("w-full h-full object-cover transition-transform duration-300 group-hover:scale-105", classNames?.image),
7926
- "data-cimplify-service-card-image": true
8011
+ type: "search",
8012
+ value: searchQuery,
8013
+ onChange: (e) => onSearchChange(e.target.value),
8014
+ placeholder: "Search...",
8015
+ className: "w-full h-10 pl-10 pr-4 text-sm border border-border rounded-lg bg-background outline-none focus:ring-2 focus:ring-primary/10 focus:border-primary/30 transition-all"
7927
8016
  }
7928
8017
  )
7929
- }
7930
- ),
7931
- /* @__PURE__ */ jsxs("div", { "data-cimplify-service-card-body": true, className: cn("p-4 flex flex-col gap-1.5", classNames?.body), children: [
7932
- /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-name": true, className: cn("font-semibold text-foreground leading-tight", classNames?.name), children: service.name }),
7933
- service.description && /* @__PURE__ */ jsx(
7934
- "span",
8018
+ ] })
8019
+ ] }),
8020
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
8021
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
8022
+ /* @__PURE__ */ jsx(
8023
+ "button",
8024
+ {
8025
+ onClick: () => onCategoryChange(null),
8026
+ className: cn(
8027
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8028
+ !selectedCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8029
+ ),
8030
+ children: "All"
8031
+ }
8032
+ ),
8033
+ categories.map((cat) => /* @__PURE__ */ jsx(
8034
+ "button",
8035
+ {
8036
+ onClick: () => onCategoryChange(selectedCategory === cat.id ? null : cat.id),
8037
+ className: cn(
8038
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8039
+ selectedCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8040
+ ),
8041
+ children: cat.name
8042
+ },
8043
+ cat.id
8044
+ ))
8045
+ ] }),
8046
+ /* @__PURE__ */ jsxs(
8047
+ "select",
7935
8048
  {
7936
- "data-cimplify-service-card-description": true,
7937
- className: cn("text-sm text-muted-foreground line-clamp-2", classNames?.description),
7938
- children: service.description
8049
+ value: `${sortBy}:${sortOrder}`,
8050
+ onChange: (e) => {
8051
+ const [by, order] = e.target.value.split(":");
8052
+ onSortChange(by, order);
8053
+ },
8054
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none shrink-0",
8055
+ children: [
8056
+ /* @__PURE__ */ jsx("option", { value: "created_at:desc", children: "Newest" }),
8057
+ /* @__PURE__ */ jsx("option", { value: "price:asc", children: "Price: Low to High" }),
8058
+ /* @__PURE__ */ jsx("option", { value: "price:desc", children: "Price: High to Low" }),
8059
+ /* @__PURE__ */ jsx("option", { value: "name:asc", children: "Name: A-Z" })
8060
+ ]
7939
8061
  }
7940
- ),
7941
- /* @__PURE__ */ jsxs("div", { "data-cimplify-service-card-meta": true, className: cn("flex items-center gap-2 mt-1 text-sm", classNames?.meta), children: [
7942
- /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-duration": true, className: cn("text-muted-foreground", classNames?.duration), children: formatDuration4(service.duration_minutes, service.duration_unit) }),
7943
- service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-price": true, className: cn("font-medium text-foreground", classNames?.price), children: /* @__PURE__ */ jsx(Price, { amount: service.price }) })
7944
- ] })
8062
+ )
7945
8063
  ] }),
7946
- !href && onBook && /* @__PURE__ */ jsx("span", { "data-cimplify-service-card-action": true, className: cn("px-4 pb-4 pt-1 text-sm font-medium text-primary", classNames?.action), children: actionLabel })
8064
+ /* @__PURE__ */ jsxs("div", { className: hasSidebar ? "flex gap-6" : "", children: [
8065
+ hasSidebar && /* @__PURE__ */ jsxs("aside", { className: "hidden lg:block w-60 shrink-0 space-y-6", children: [
8066
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
8067
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "In stock only" }),
8068
+ /* @__PURE__ */ jsx(
8069
+ "button",
8070
+ {
8071
+ onClick: () => onInStockChange(!inStockOnly),
8072
+ className: cn("w-10 h-6 rounded-full transition-colors relative", inStockOnly ? "bg-foreground" : "bg-border"),
8073
+ children: /* @__PURE__ */ jsx("span", { className: cn("absolute top-1 w-4 h-4 rounded-full bg-background transition-transform shadow-sm", inStockOnly ? "left-5" : "left-1") })
8074
+ }
8075
+ )
8076
+ ] }),
8077
+ /* @__PURE__ */ jsxs("div", { children: [
8078
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: "Price Range" }),
8079
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8080
+ /* @__PURE__ */ jsx(
8081
+ "input",
8082
+ {
8083
+ type: "number",
8084
+ placeholder: "Min",
8085
+ value: minPrice,
8086
+ onChange: (e) => onPriceRangeChange(e.target.value, maxPrice),
8087
+ 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"
8088
+ }
8089
+ ),
8090
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-xs", children: "\u2013" }),
8091
+ /* @__PURE__ */ jsx(
8092
+ "input",
8093
+ {
8094
+ type: "number",
8095
+ placeholder: "Max",
8096
+ value: maxPrice,
8097
+ onChange: (e) => onPriceRangeChange(minPrice, e.target.value),
8098
+ 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"
8099
+ }
8100
+ )
8101
+ ] })
8102
+ ] }),
8103
+ facets?.map((facet) => /* @__PURE__ */ jsxs("div", { children: [
8104
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: facet.name }),
8105
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: facet.values.slice(0, 8).map((fv) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
8106
+ /* @__PURE__ */ jsx("input", { type: "checkbox", className: "w-3.5 h-3.5 accent-foreground rounded" }),
8107
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors flex-1", children: fv.value }),
8108
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60", children: fv.count })
8109
+ ] }, fv.value)) })
8110
+ ] }, facet.slug)),
8111
+ availableTags && availableTags.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
8112
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: "Tags" }),
8113
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: availableTags.map((tag) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
8114
+ /* @__PURE__ */ jsx(
8115
+ "input",
8116
+ {
8117
+ type: "checkbox",
8118
+ checked: selectedTags.includes(tag),
8119
+ onChange: () => onTagToggle(tag),
8120
+ className: "w-3.5 h-3.5 accent-foreground rounded"
8121
+ }
8122
+ ),
8123
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors", children: tag })
8124
+ ] }, tag)) })
8125
+ ] })
8126
+ ] }),
8127
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
8128
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4 animate-pulse", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
8129
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
8130
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
8131
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
8132
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
8133
+ ] })
8134
+ ] }, i)) }) : products.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
8135
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No products found" }),
8136
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try adjusting your filters" })
8137
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: products.map(
8138
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
8139
+ ProductCard,
8140
+ {
8141
+ product,
8142
+ renderImage,
8143
+ renderLink,
8144
+ onQuickAdd
8145
+ },
8146
+ product.id
8147
+ )
8148
+ ) }),
8149
+ totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 pt-8", children: [
8150
+ /* @__PURE__ */ jsx(
8151
+ "button",
8152
+ {
8153
+ disabled: page <= 1,
8154
+ onClick: () => onPageChange(page - 1),
8155
+ className: "text-sm px-3 py-1.5 border border-border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
8156
+ children: "Previous"
8157
+ }
8158
+ ),
8159
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums px-2", children: [
8160
+ page,
8161
+ " / ",
8162
+ totalPages
8163
+ ] }),
8164
+ /* @__PURE__ */ jsx(
8165
+ "button",
8166
+ {
8167
+ disabled: page >= totalPages,
8168
+ onClick: () => onPageChange(page + 1),
8169
+ className: "text-sm px-3 py-1.5 border border-border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
8170
+ children: "Next"
8171
+ }
8172
+ )
8173
+ ] })
8174
+ ] })
8175
+ ] })
7947
8176
  ] });
7948
- const cardClasses = cn(
7949
- "group block w-full rounded-xl border border-border bg-background text-left transition-shadow duration-200 hover:shadow-md",
7950
- !service.is_available && "opacity-60",
7951
- className,
7952
- classNames?.root
7953
- );
7954
- if (href) {
7955
- return /* @__PURE__ */ jsx(
7956
- "a",
7957
- {
7958
- href,
7959
- "data-cimplify-service-card": true,
7960
- "data-available": service.is_available || void 0,
7961
- className: cn(cardClasses, "no-underline text-[inherit]"),
7962
- children: cardBody
7963
- }
7964
- );
7965
- }
7966
- return /* @__PURE__ */ jsx(
7967
- "button",
7968
- {
7969
- type: "button",
7970
- onClick: () => onBook?.(service),
7971
- disabled: !service.is_available,
7972
- "data-cimplify-service-card": true,
7973
- "data-available": service.is_available || void 0,
7974
- className: cn(cardClasses, "cursor-pointer font-[inherit] p-0 border-border"),
7975
- children: cardBody
7976
- }
7977
- );
7978
8177
  }
7979
- function ServiceGrid({
7980
- services: servicesProp,
7981
- columns,
7982
- onServiceSelect,
7983
- getServiceHref,
8178
+ function CompactCatalogueLayout({
8179
+ products,
8180
+ categories,
8181
+ isLoading,
8182
+ selectedCategory,
8183
+ onCategoryChange,
8184
+ searchQuery,
8185
+ onSearchChange,
7984
8186
  renderCard,
7985
8187
  renderImage,
7986
- availableOnly = true,
7987
- actionLabel,
7988
- emptyMessage = "No services available",
7989
- className,
7990
- classNames
8188
+ renderLink,
8189
+ onQuickAdd,
8190
+ title = "Menu",
8191
+ className
7991
8192
  }) {
7992
- const rawId = React3.useId();
7993
- const gridId = `cimplify-service-grid-${rawId.replace(/:/g, "")}`;
7994
- const { services: fetched, isLoading } = useServices({
7995
- enabled: servicesProp === void 0
7996
- });
7997
- const allServices = servicesProp ?? fetched;
7998
- const services = availableOnly ? allServices.filter((s) => s.is_available) : allServices;
7999
- const sm = columns?.sm ?? 1;
8000
- const md = columns?.md ?? 2;
8001
- const lg = columns?.lg ?? 3;
8002
- const xl = columns?.xl ?? 4;
8003
- if (isLoading && services.length === 0) {
8004
- return /* @__PURE__ */ jsx(
8005
- "div",
8006
- {
8007
- "data-cimplify-service-grid": true,
8008
- "aria-busy": "true",
8009
- className: cn(className, classNames?.root, classNames?.loading)
8010
- }
8011
- );
8012
- }
8013
- if (services.length === 0) {
8014
- return /* @__PURE__ */ jsx(
8015
- "div",
8016
- {
8017
- "data-cimplify-service-grid": true,
8018
- "data-empty": true,
8019
- className: cn(className, classNames?.root, classNames?.empty),
8020
- children: /* @__PURE__ */ jsx("p", { children: emptyMessage })
8021
- }
8022
- );
8023
- }
8024
- const css = [
8025
- `#${gridId}{display:grid;grid-template-columns:repeat(${sm},1fr);gap:1rem}`,
8026
- `@media(min-width:768px){#${gridId}{grid-template-columns:repeat(${md},1fr)}}`,
8027
- `@media(min-width:1024px){#${gridId}{grid-template-columns:repeat(${lg},1fr)}}`,
8028
- `@media(min-width:1280px){#${gridId}{grid-template-columns:repeat(${xl},1fr)}}`
8029
- ].join("");
8030
- return /* @__PURE__ */ jsxs(Fragment, { children: [
8031
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: css } }),
8032
- /* @__PURE__ */ jsx(
8033
- "div",
8034
- {
8035
- id: gridId,
8036
- "data-cimplify-service-grid": true,
8037
- className: cn(className, classNames?.root),
8038
- children: services.map((service) => /* @__PURE__ */ jsx(
8039
- "div",
8193
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-layout": "compact", className: cn("space-y-6", className), children: [
8194
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
8195
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-3", children: [
8196
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1 flex-1", children: [
8197
+ /* @__PURE__ */ jsx(
8198
+ "button",
8040
8199
  {
8041
- "data-cimplify-service-grid-item": true,
8042
- className: classNames?.item,
8043
- children: renderCard ? renderCard(service) : /* @__PURE__ */ jsx(
8044
- ServiceCard,
8045
- {
8046
- service,
8047
- onBook: onServiceSelect,
8048
- href: getServiceHref?.(service),
8049
- actionLabel,
8050
- renderImage
8051
- }
8052
- )
8200
+ onClick: () => onCategoryChange(null),
8201
+ className: cn(
8202
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8203
+ !selectedCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8204
+ ),
8205
+ children: "All"
8206
+ }
8207
+ ),
8208
+ categories.map((cat) => /* @__PURE__ */ jsx(
8209
+ "button",
8210
+ {
8211
+ onClick: () => onCategoryChange(selectedCategory === cat.id ? null : cat.id),
8212
+ className: cn(
8213
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
8214
+ selectedCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
8215
+ ),
8216
+ children: cat.name
8053
8217
  },
8054
- service.id
8218
+ cat.id
8055
8219
  ))
8056
- }
8057
- )
8220
+ ] }),
8221
+ /* @__PURE__ */ jsxs("div", { className: "relative w-full sm:max-w-[200px]", children: [
8222
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
8223
+ /* @__PURE__ */ jsx(
8224
+ "input",
8225
+ {
8226
+ type: "search",
8227
+ value: searchQuery,
8228
+ onChange: (e) => onSearchChange(e.target.value),
8229
+ placeholder: "Search...",
8230
+ 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"
8231
+ }
8232
+ )
8233
+ ] })
8234
+ ] }),
8235
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5 animate-pulse", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
8236
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
8237
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
8238
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
8239
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
8240
+ ] })
8241
+ ] }, i)) }) : products.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
8242
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "No items found" }),
8243
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different category or search" })
8244
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: products.map(
8245
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
8246
+ ProductCard,
8247
+ {
8248
+ product,
8249
+ renderImage,
8250
+ renderLink,
8251
+ onQuickAdd
8252
+ },
8253
+ product.id
8254
+ )
8255
+ ) })
8058
8256
  ] });
8059
8257
  }
8258
+ var CatalogueTemplate = /* @__PURE__ */ ((CatalogueTemplate2) => {
8259
+ CatalogueTemplate2["Default"] = "default";
8260
+ CatalogueTemplate2["Compact"] = "compact";
8261
+ return CatalogueTemplate2;
8262
+ })(CatalogueTemplate || {});
8263
+ var BUILT_IN_LAYOUTS = {
8264
+ ["default" /* Default */]: DefaultCatalogueLayout,
8265
+ ["compact" /* Compact */]: CompactCatalogueLayout
8266
+ };
8267
+ function useDebounce(value, delay) {
8268
+ const [debounced, setDebounced] = React3.useState(value);
8269
+ React3.useEffect(() => {
8270
+ const timer = setTimeout(() => setDebounced(value), delay);
8271
+ return () => clearTimeout(timer);
8272
+ }, [value, delay]);
8273
+ return debounced;
8274
+ }
8060
8275
  function CataloguePage({
8061
- title = "Products",
8276
+ template,
8277
+ layouts,
8278
+ title,
8062
8279
  products: productsProp,
8063
8280
  categories: categoriesProp,
8064
- showFilter = true,
8065
- showSearch = true,
8066
- showSort = false,
8067
- showInStockFilter = false,
8068
- showPriceRange = false,
8069
- showTagsFilter = false,
8281
+ facets,
8070
8282
  availableTags,
8071
- defaultSort,
8072
8283
  pageSize,
8073
- onProductClick,
8074
- onCategoryClick,
8284
+ defaultSort,
8075
8285
  renderCard,
8076
8286
  renderImage,
8077
- columns,
8287
+ renderLink,
8288
+ onQuickAdd,
8289
+ onProductClick,
8078
8290
  className,
8079
8291
  classNames
8080
8292
  }) {
8081
- const [selectedCategoryId, setSelectedCategoryId] = useState(null);
8293
+ const [selectedCategory, setSelectedCategory] = useState(null);
8082
8294
  const [searchQuery, setSearchQuery] = useState("");
8083
- const [sortBy, setSortBy] = useState(defaultSort?.by ?? "name");
8084
- const [sortOrder, setSortOrder] = useState(defaultSort?.order ?? "asc");
8295
+ const [sortBy, setSortBy] = useState(defaultSort?.by ?? "created_at");
8296
+ const [sortOrder, setSortOrder] = useState(defaultSort?.order ?? "desc");
8085
8297
  const [inStockOnly, setInStockOnly] = useState(false);
8086
8298
  const [selectedTags, setSelectedTags] = useState([]);
8087
8299
  const [minPrice, setMinPrice] = useState("");
8088
8300
  const [maxPrice, setMaxPrice] = useState("");
8089
8301
  const [page, setPage] = useState(1);
8090
8302
  const debouncedSearch = useDebounce(searchQuery, 300);
8091
- const { products: fetchedProducts, isLoading: productsLoading, pagination } = useProducts({
8303
+ const { products: fetchedProducts, isLoading, pagination } = useProducts({
8092
8304
  enabled: productsProp === void 0,
8093
- category: selectedCategoryId ?? void 0,
8305
+ category: selectedCategory ?? void 0,
8094
8306
  search: debouncedSearch.length >= 2 ? debouncedSearch : void 0,
8095
8307
  sort_by: sortBy,
8096
8308
  sort_order: sortOrder,
@@ -8102,185 +8314,66 @@ function CataloguePage({
8102
8314
  limit: pageSize
8103
8315
  });
8104
8316
  const { categories: fetchedCategories } = useCategories({
8105
- enabled: showFilter && categoriesProp === void 0
8317
+ enabled: categoriesProp === void 0
8106
8318
  });
8107
- const allProducts = productsProp ?? fetchedProducts;
8319
+ const products = productsProp ?? fetchedProducts;
8108
8320
  const categories = categoriesProp ?? fetchedCategories;
8109
- const handleCategorySelect = useCallback(
8110
- (id) => {
8111
- setSelectedCategoryId(id);
8112
- setPage(1);
8113
- if (id) {
8114
- const cat = categories.find((c) => c.id === id);
8115
- if (cat) onCategoryClick?.(cat);
8116
- }
8117
- },
8118
- [categories, onCategoryClick]
8119
- );
8120
- const handleTagToggle = useCallback((tag) => {
8121
- setSelectedTags(
8321
+ const totalPages = pagination?.total_pages ?? 1;
8322
+ const handleCategoryChange = useCallback((id) => {
8323
+ setSelectedCategory(id);
8324
+ setPage(1);
8325
+ }, []);
8326
+ const handleSortChange = useCallback((by, order) => {
8327
+ setSortBy(by);
8328
+ setSortOrder(order);
8329
+ setPage(1);
8330
+ }, []);
8331
+ const handleTagToggle = useCallback((tag) => {
8332
+ setSelectedTags(
8122
8333
  (prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
8123
8334
  );
8124
8335
  setPage(1);
8125
8336
  }, []);
8126
- const totalPages = pagination?.total_pages ?? 1;
8127
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-page": true, className: cn(className, classNames?.root), children: [
8128
- /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-header": true, className: classNames?.header, children: [
8129
- /* @__PURE__ */ jsx("h1", { "data-cimplify-catalogue-title": true, className: classNames?.title, children: title }),
8130
- showSearch && /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-search": true, className: classNames?.searchContainer, children: /* @__PURE__ */ jsx(
8131
- SearchInput,
8132
- {
8133
- onResultClick: onProductClick,
8134
- searchOptions: { category: selectedCategoryId ?? void 0 }
8135
- }
8136
- ) })
8137
- ] }),
8138
- showFilter && categories.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-filter": true, className: classNames?.filterContainer, children: /* @__PURE__ */ jsx(
8139
- CategoryFilter,
8140
- {
8141
- selectedId: selectedCategoryId,
8142
- onSelect: handleCategorySelect
8143
- }
8144
- ) }),
8145
- (showSort || showInStockFilter || showPriceRange || showTagsFilter) && /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-toolbar": true, className: cn("flex flex-wrap items-center gap-3", classNames?.toolbar), children: [
8146
- showSort && /* @__PURE__ */ jsxs(
8147
- "select",
8148
- {
8149
- "data-cimplify-sort": true,
8150
- value: `${sortBy}:${sortOrder}`,
8151
- onChange: (e) => {
8152
- const [by, order] = e.target.value.split(":");
8153
- setSortBy(by);
8154
- setSortOrder(order);
8155
- setPage(1);
8156
- },
8157
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm",
8158
- children: [
8159
- /* @__PURE__ */ jsx("option", { value: "name:asc", children: "Name A\u2013Z" }),
8160
- /* @__PURE__ */ jsx("option", { value: "name:desc", children: "Name Z\u2013A" }),
8161
- /* @__PURE__ */ jsx("option", { value: "price:asc", children: "Price: Low to High" }),
8162
- /* @__PURE__ */ jsx("option", { value: "price:desc", children: "Price: High to Low" }),
8163
- /* @__PURE__ */ jsx("option", { value: "created_at:desc", children: "Newest" }),
8164
- /* @__PURE__ */ jsx("option", { value: "created_at:asc", children: "Oldest" }),
8165
- /* @__PURE__ */ jsx("option", { value: "updated_at:desc", children: "Recently Updated" })
8166
- ]
8167
- }
8168
- ),
8169
- showInStockFilter && /* @__PURE__ */ jsxs("label", { "data-cimplify-stock-filter": true, className: "flex items-center gap-1.5 text-sm cursor-pointer", children: [
8170
- /* @__PURE__ */ jsx(
8171
- "input",
8172
- {
8173
- type: "checkbox",
8174
- checked: inStockOnly,
8175
- onChange: (e) => {
8176
- setInStockOnly(e.target.checked);
8177
- setPage(1);
8178
- },
8179
- className: "accent-primary"
8180
- }
8181
- ),
8182
- "In stock only"
8183
- ] }),
8184
- showPriceRange && /* @__PURE__ */ jsxs("div", { "data-cimplify-price-range": true, className: "flex items-center gap-1.5", children: [
8185
- /* @__PURE__ */ jsx(
8186
- "input",
8187
- {
8188
- type: "number",
8189
- placeholder: "Min",
8190
- value: minPrice,
8191
- onChange: (e) => {
8192
- setMinPrice(e.target.value);
8193
- setPage(1);
8194
- },
8195
- className: "w-20 rounded-md border border-input bg-background px-2 py-1.5 text-sm",
8196
- min: 0,
8197
- step: "0.01"
8198
- }
8199
- ),
8200
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "\u2013" }),
8201
- /* @__PURE__ */ jsx(
8202
- "input",
8203
- {
8204
- type: "number",
8205
- placeholder: "Max",
8206
- value: maxPrice,
8207
- onChange: (e) => {
8208
- setMaxPrice(e.target.value);
8209
- setPage(1);
8210
- },
8211
- className: "w-20 rounded-md border border-input bg-background px-2 py-1.5 text-sm",
8212
- min: 0,
8213
- step: "0.01"
8214
- }
8215
- )
8216
- ] }),
8217
- showTagsFilter && availableTags && availableTags.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-tags-filter": true, className: "flex flex-wrap gap-1.5", children: availableTags.map((tag) => /* @__PURE__ */ jsx(
8218
- "button",
8219
- {
8220
- type: "button",
8221
- onClick: () => handleTagToggle(tag),
8222
- className: cn(
8223
- "rounded-full px-3 py-1 text-xs font-medium border transition-colors",
8224
- selectedTags.includes(tag) ? "bg-primary text-primary-foreground border-primary" : "bg-background text-foreground border-input hover:bg-muted"
8225
- ),
8226
- children: tag
8227
- },
8228
- tag
8229
- )) })
8230
- ] }),
8231
- /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-grid": true, className: classNames?.gridContainer, children: productsLoading && !productsProp ? /* @__PURE__ */ jsx(
8232
- "div",
8233
- {
8234
- "data-cimplify-catalogue-loading": true,
8235
- "aria-busy": "true",
8236
- className: classNames?.loading
8237
- }
8238
- ) : /* @__PURE__ */ jsx(
8239
- ProductGrid,
8240
- {
8241
- products: allProducts,
8242
- renderCard,
8243
- renderImage,
8244
- columns,
8245
- emptyMessage: "No products found"
8246
- }
8247
- ) }),
8248
- totalPages > 1 && /* @__PURE__ */ jsxs("div", { "data-cimplify-catalogue-pagination": true, className: cn("flex items-center justify-center gap-2 pt-6", classNames?.pagination), children: [
8249
- /* @__PURE__ */ jsx(
8250
- "button",
8251
- {
8252
- type: "button",
8253
- disabled: page <= 1,
8254
- onClick: () => setPage((p) => Math.max(1, p - 1)),
8255
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm disabled:opacity-40",
8256
- children: "Previous"
8257
- }
8258
- ),
8259
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground tabular-nums", children: [
8260
- page,
8261
- " / ",
8262
- totalPages
8263
- ] }),
8264
- /* @__PURE__ */ jsx(
8265
- "button",
8266
- {
8267
- type: "button",
8268
- disabled: page >= totalPages,
8269
- onClick: () => setPage((p) => p + 1),
8270
- className: "rounded-md border border-input bg-background px-3 py-1.5 text-sm disabled:opacity-40",
8271
- children: "Next"
8272
- }
8273
- )
8274
- ] })
8275
- ] });
8276
- }
8277
- function useDebounce(value, delay) {
8278
- const [debounced, setDebounced] = React3.useState(value);
8279
- React3.useEffect(() => {
8280
- const timer = setTimeout(() => setDebounced(value), delay);
8281
- return () => clearTimeout(timer);
8282
- }, [value, delay]);
8283
- return debounced;
8337
+ const handlePriceRangeChange = useCallback((min, max) => {
8338
+ setMinPrice(min);
8339
+ setMaxPrice(max);
8340
+ setPage(1);
8341
+ }, []);
8342
+ const key = template ?? "default" /* Default */;
8343
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS[key] ?? DefaultCatalogueLayout;
8344
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-catalogue-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
8345
+ Layout,
8346
+ {
8347
+ products,
8348
+ categories,
8349
+ facets,
8350
+ isLoading,
8351
+ selectedCategory,
8352
+ onCategoryChange: handleCategoryChange,
8353
+ searchQuery,
8354
+ onSearchChange: setSearchQuery,
8355
+ sortBy,
8356
+ sortOrder,
8357
+ onSortChange: handleSortChange,
8358
+ inStockOnly,
8359
+ onInStockChange: setInStockOnly,
8360
+ selectedTags,
8361
+ availableTags,
8362
+ onTagToggle: handleTagToggle,
8363
+ minPrice,
8364
+ maxPrice,
8365
+ onPriceRangeChange: handlePriceRangeChange,
8366
+ page,
8367
+ totalPages,
8368
+ onPageChange: setPage,
8369
+ renderCard,
8370
+ renderImage,
8371
+ renderLink,
8372
+ onQuickAdd,
8373
+ onProductClick,
8374
+ title
8375
+ }
8376
+ ) });
8284
8377
  }
8285
8378
  function TwoColumnGrid({
8286
8379
  left,
@@ -8910,7 +9003,7 @@ var ProductTemplate = /* @__PURE__ */ ((ProductTemplate2) => {
8910
9003
  ProductTemplate2["Physical"] = "physical";
8911
9004
  return ProductTemplate2;
8912
9005
  })(ProductTemplate || {});
8913
- var BUILT_IN_LAYOUTS = {
9006
+ var BUILT_IN_LAYOUTS2 = {
8914
9007
  ["food" /* Food */]: FoodProductLayout,
8915
9008
  ["wholesale" /* Wholesale */]: WholesaleProductLayout,
8916
9009
  ["service" /* Service */]: ServiceProductLayout,
@@ -8947,8 +9040,8 @@ function resolveLayout(product, pages, templates) {
8947
9040
  if (templates?.[key]) {
8948
9041
  return templates[key];
8949
9042
  }
8950
- if (BUILT_IN_LAYOUTS[key]) {
8951
- return BUILT_IN_LAYOUTS[key];
9043
+ if (BUILT_IN_LAYOUTS2[key]) {
9044
+ return BUILT_IN_LAYOUTS2[key];
8952
9045
  }
8953
9046
  return DefaultProductLayout;
8954
9047
  }
@@ -9006,56 +9099,168 @@ function ProductPage({
9006
9099
  }
9007
9100
  ) });
9008
9101
  }
9009
- function CartPage({
9010
- title = "Your Cart",
9102
+ function DefaultCartLayout({
9103
+ cart,
9011
9104
  onCheckout,
9012
9105
  onContinueShopping,
9013
9106
  onDiscountApply,
9014
9107
  onDiscountClear,
9015
9108
  showDiscount = true,
9016
- showContinueShopping = true,
9017
9109
  checkoutLabel = "Proceed to Checkout",
9018
- className,
9019
- classNames
9110
+ className
9020
9111
  }) {
9021
- const { isEmpty, subtotal } = useCart();
9022
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page": true, className: cn(className, classNames?.root), children: [
9023
- /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page-header": true, className: classNames?.header, children: [
9024
- /* @__PURE__ */ jsx("h1", { "data-cimplify-cart-page-title": true, className: classNames?.title, children: title }),
9025
- showContinueShopping && /* @__PURE__ */ jsx(
9112
+ if (cart.isEmpty) {
9113
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("text-center py-20", className), children: [
9114
+ /* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto text-muted-foreground/30", fill: "none", stroke: "currentColor", strokeWidth: "1", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }),
9115
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium mt-4", children: "Your cart is empty" }),
9116
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Add some items to get started" }),
9117
+ onContinueShopping && /* @__PURE__ */ jsx(
9026
9118
  "button",
9027
9119
  {
9028
- type: "button",
9029
9120
  onClick: onContinueShopping,
9030
- "data-cimplify-cart-continue": true,
9031
- className: classNames?.continueButton,
9032
- children: "Continue Shopping"
9121
+ className: "text-sm font-medium text-primary mt-4 hover:underline",
9122
+ children: "Continue shopping"
9033
9123
  }
9034
9124
  )
9035
- ] }),
9036
- /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-page-content": true, className: classNames?.content, children: [
9037
- /* @__PURE__ */ jsx(CartSummary, {}),
9038
- showDiscount && !isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page-discount": true, className: classNames?.discount, children: /* @__PURE__ */ jsx(
9039
- DiscountInput,
9125
+ ] });
9126
+ }
9127
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "default", className: cn("space-y-6", className), children: [
9128
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9129
+ /* @__PURE__ */ jsxs("h1", { className: "text-2xl font-bold tracking-tight", children: [
9130
+ "Your Cart (",
9131
+ cart.itemCount,
9132
+ " ",
9133
+ cart.itemCount === 1 ? "item" : "items",
9134
+ ")"
9135
+ ] }),
9136
+ onContinueShopping && /* @__PURE__ */ jsx(
9137
+ "button",
9040
9138
  {
9041
- orderSubtotal: subtotal.toString(),
9042
- onApply: onDiscountApply,
9043
- onClear: onDiscountClear
9139
+ onClick: onContinueShopping,
9140
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
9141
+ children: "Continue shopping"
9044
9142
  }
9045
- ) })
9143
+ )
9144
+ ] }),
9145
+ /* @__PURE__ */ jsxs("div", { className: "grid lg:grid-cols-[1fr_380px] gap-8", children: [
9146
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(CartSummary, {}) }),
9147
+ /* @__PURE__ */ jsx("div", { className: "lg:sticky lg:top-6 h-fit space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "border border-border rounded-[14px] p-6 space-y-4", children: [
9148
+ /* @__PURE__ */ jsx("h2", { className: "font-semibold", children: "Order Summary" }),
9149
+ showDiscount && /* @__PURE__ */ jsx(
9150
+ DiscountInput,
9151
+ {
9152
+ orderSubtotal: cart.subtotal.toString(),
9153
+ onApply: onDiscountApply,
9154
+ onClear: onDiscountClear
9155
+ }
9156
+ ),
9157
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm", children: [
9158
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9159
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
9160
+ /* @__PURE__ */ jsx(Price, { amount: cart.subtotal })
9161
+ ] }),
9162
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9163
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Tax" }),
9164
+ /* @__PURE__ */ jsx(Price, { amount: cart.tax })
9165
+ ] }),
9166
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between font-semibold text-base pt-2 border-t border-border", children: [
9167
+ /* @__PURE__ */ jsx("span", { children: "Total" }),
9168
+ /* @__PURE__ */ jsx(Price, { amount: cart.total })
9169
+ ] })
9170
+ ] }),
9171
+ /* @__PURE__ */ jsx(
9172
+ "button",
9173
+ {
9174
+ onClick: onCheckout,
9175
+ className: "w-full h-12 bg-foreground text-background font-medium text-sm rounded-lg hover:bg-foreground/90 transition-colors",
9176
+ children: checkoutLabel
9177
+ }
9178
+ )
9179
+ ] }) })
9180
+ ] })
9181
+ ] });
9182
+ }
9183
+ function CompactCartLayout({
9184
+ cart,
9185
+ onCheckout,
9186
+ onContinueShopping,
9187
+ checkoutLabel = "Place Order",
9188
+ className
9189
+ }) {
9190
+ if (cart.isEmpty) {
9191
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "compact", className: cn("text-center py-16", className), children: [
9192
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "Your order is empty" }),
9193
+ onContinueShopping && /* @__PURE__ */ jsx("button", { onClick: onContinueShopping, className: "text-sm font-medium text-primary mt-3 hover:underline", children: "Browse menu" })
9194
+ ] });
9195
+ }
9196
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-cart-layout": "compact", className: cn("max-w-lg mx-auto space-y-4", className), children: [
9197
+ /* @__PURE__ */ jsxs("h1", { className: "text-xl font-bold tracking-tight", children: [
9198
+ "Your Order (",
9199
+ cart.itemCount,
9200
+ ")"
9201
+ ] }),
9202
+ /* @__PURE__ */ jsx(CartSummary, {}),
9203
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm pt-4 border-t border-border", children: [
9204
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9205
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Subtotal" }),
9206
+ /* @__PURE__ */ jsx(Price, { amount: cart.subtotal })
9207
+ ] }),
9208
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
9209
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Tax" }),
9210
+ /* @__PURE__ */ jsx(Price, { amount: cart.tax })
9211
+ ] }),
9212
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between font-semibold text-base pt-2 border-t border-border", children: [
9213
+ /* @__PURE__ */ jsx("span", { children: "Total" }),
9214
+ /* @__PURE__ */ jsx(Price, { amount: cart.total })
9215
+ ] })
9046
9216
  ] }),
9047
- !isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page-footer": true, className: classNames?.footer, children: /* @__PURE__ */ jsx(
9217
+ /* @__PURE__ */ jsx(
9048
9218
  "button",
9049
9219
  {
9050
- type: "button",
9051
9220
  onClick: onCheckout,
9052
- "data-cimplify-cart-checkout-button": true,
9053
- className: classNames?.checkoutButton,
9221
+ className: "w-full h-12 bg-foreground text-background font-medium text-sm rounded-lg hover:bg-foreground/90 transition-colors",
9054
9222
  children: checkoutLabel
9055
9223
  }
9056
- ) })
9224
+ )
9057
9225
  ] });
9058
9226
  }
9227
+ var CartTemplate = /* @__PURE__ */ ((CartTemplate2) => {
9228
+ CartTemplate2["Default"] = "default";
9229
+ CartTemplate2["Compact"] = "compact";
9230
+ return CartTemplate2;
9231
+ })(CartTemplate || {});
9232
+ var BUILT_IN_LAYOUTS3 = {
9233
+ ["default" /* Default */]: DefaultCartLayout,
9234
+ ["compact" /* Compact */]: CompactCartLayout
9235
+ };
9236
+ function CartPage({
9237
+ template,
9238
+ layouts,
9239
+ onCheckout,
9240
+ onContinueShopping,
9241
+ onDiscountApply,
9242
+ onDiscountClear,
9243
+ showDiscount = true,
9244
+ checkoutLabel,
9245
+ className,
9246
+ classNames
9247
+ }) {
9248
+ const cart = useCart();
9249
+ const key = template ?? "default" /* Default */;
9250
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS3[key] ?? DefaultCartLayout;
9251
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-cart-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
9252
+ Layout,
9253
+ {
9254
+ cart,
9255
+ onCheckout,
9256
+ onContinueShopping,
9257
+ onDiscountApply,
9258
+ onDiscountClear,
9259
+ showDiscount,
9260
+ checkoutLabel
9261
+ }
9262
+ ) });
9263
+ }
9059
9264
  function CheckoutPage({
9060
9265
  title = "Checkout",
9061
9266
  onComplete,
@@ -9079,88 +9284,426 @@ function CheckoutPage({
9079
9284
  )
9080
9285
  ] });
9081
9286
  }
9082
- function CollectionPage({
9083
- collectionId,
9084
- collection: collectionProp,
9085
- products: productsProp,
9287
+ function DefaultCollectionLayout({
9288
+ collection,
9289
+ products,
9086
9290
  renderCard,
9087
9291
  renderImage,
9088
- columns,
9089
- className,
9090
- classNames
9292
+ renderLink,
9293
+ onQuickAdd,
9294
+ className
9091
9295
  }) {
9092
- const {
9093
- collection: fetchedCollection,
9094
- products: fetchedProducts,
9095
- isLoading
9096
- } = useCollection(collectionProp ? null : collectionId, {
9097
- enabled: !collectionProp
9098
- });
9099
- const collection = collectionProp ?? fetchedCollection;
9100
- const products = productsProp ?? fetchedProducts;
9101
- if (isLoading && !collection) {
9102
- return /* @__PURE__ */ jsx(
9103
- "div",
9104
- {
9105
- "data-cimplify-collection-page": true,
9106
- "aria-busy": "true",
9107
- className: cn(className, classNames?.root, classNames?.loading)
9108
- }
9109
- );
9110
- }
9111
- if (!collection) {
9112
- return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx("p", { children: "Collection not found." }) });
9113
- }
9114
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: [
9115
- /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-header": true, className: classNames?.header, children: [
9296
+ const [searchQuery, setSearchQuery] = useState("");
9297
+ const [activeTag, setActiveTag] = useState(null);
9298
+ const collectionTags = useMemo(() => {
9299
+ const tagSet = /* @__PURE__ */ new Set();
9300
+ for (const p of products) {
9301
+ if (p.tags) {
9302
+ for (const t of p.tags) tagSet.add(t);
9303
+ }
9304
+ }
9305
+ return Array.from(tagSet).slice(0, 6);
9306
+ }, [products]);
9307
+ const filtered = useMemo(() => {
9308
+ let result = products;
9309
+ if (searchQuery.trim().length >= 2) {
9310
+ const q = searchQuery.toLowerCase();
9311
+ result = result.filter(
9312
+ (p) => p.name.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q)
9313
+ );
9314
+ }
9315
+ if (activeTag) {
9316
+ result = result.filter((p) => p.tags?.includes(activeTag));
9317
+ }
9318
+ return result;
9319
+ }, [products, searchQuery, activeTag]);
9320
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "default", className: cn("space-y-8", className), children: [
9321
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-hero": true, className: "relative overflow-hidden rounded-2xl bg-muted", children: [
9116
9322
  collection.image_url && /* @__PURE__ */ jsx(
9117
9323
  "img",
9118
9324
  {
9119
9325
  src: collection.image_url,
9120
9326
  alt: collection.name,
9121
- "data-cimplify-collection-image": true,
9122
- className: classNames?.image
9327
+ className: "w-full h-64 lg:h-80 object-cover"
9123
9328
  }
9124
9329
  ),
9125
- /* @__PURE__ */ jsx("h1", { "data-cimplify-collection-title": true, className: classNames?.title, children: collection.name }),
9126
- collection.description && /* @__PURE__ */ jsx("p", { "data-cimplify-collection-description": true, className: classNames?.description, children: collection.description })
9330
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent" }),
9331
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-6 lg:p-8", children: [
9332
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl lg:text-4xl font-bold text-white tracking-tight", children: collection.name }),
9333
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-white/80 mt-2 max-w-lg text-sm lg:text-base", children: collection.description }),
9334
+ /* @__PURE__ */ jsxs("p", { className: "text-white/60 text-sm mt-2", children: [
9335
+ products.length,
9336
+ " ",
9337
+ products.length === 1 ? "item" : "items"
9338
+ ] })
9339
+ ] })
9127
9340
  ] }),
9128
- /* @__PURE__ */ jsx("div", { "data-cimplify-collection-grid": true, className: classNames?.grid, children: /* @__PURE__ */ jsx(
9129
- ProductGrid,
9130
- {
9131
- products,
9132
- renderCard,
9133
- renderImage,
9134
- columns
9135
- }
9136
- ) })
9341
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center gap-3", children: [
9342
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0 w-full sm:max-w-xs", children: [
9343
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9344
+ /* @__PURE__ */ jsx(
9345
+ "input",
9346
+ {
9347
+ type: "search",
9348
+ value: searchQuery,
9349
+ onChange: (e) => setSearchQuery(e.target.value),
9350
+ placeholder: `Search ${collection.name}...`,
9351
+ 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"
9352
+ }
9353
+ )
9354
+ ] }),
9355
+ collectionTags.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
9356
+ /* @__PURE__ */ jsx(
9357
+ "button",
9358
+ {
9359
+ onClick: () => setActiveTag(null),
9360
+ className: cn(
9361
+ "text-xs font-medium px-3 py-1.5 rounded-full transition-colors",
9362
+ !activeTag ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9363
+ ),
9364
+ children: "All"
9365
+ }
9366
+ ),
9367
+ collectionTags.map((tag) => /* @__PURE__ */ jsx(
9368
+ "button",
9369
+ {
9370
+ onClick: () => setActiveTag(activeTag === tag ? null : tag),
9371
+ className: cn(
9372
+ "text-xs font-medium px-3 py-1.5 rounded-full transition-colors",
9373
+ activeTag === tag ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9374
+ ),
9375
+ children: tag
9376
+ },
9377
+ tag
9378
+ ))
9379
+ ] })
9380
+ ] }),
9381
+ filtered.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
9382
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9383
+ ProductCard,
9384
+ {
9385
+ product,
9386
+ renderImage,
9387
+ renderLink,
9388
+ onQuickAdd
9389
+ },
9390
+ product.id
9391
+ )
9392
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
9393
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No items match your search." }),
9394
+ /* @__PURE__ */ jsx(
9395
+ "button",
9396
+ {
9397
+ onClick: () => {
9398
+ setSearchQuery("");
9399
+ setActiveTag(null);
9400
+ },
9401
+ className: "text-sm font-medium text-primary mt-2 hover:underline",
9402
+ children: "Clear filters"
9403
+ }
9404
+ )
9405
+ ] })
9137
9406
  ] });
9138
9407
  }
9139
- function OrderDetailPage({
9140
- orderId,
9141
- order,
9142
- poll = true,
9143
- onBack,
9144
- renderLineItem,
9145
- onReorder,
9146
- onStatusChange,
9147
- backLabel = "Back to orders",
9148
- className,
9149
- classNames
9408
+ function FeaturedCollectionLayout({
9409
+ collection,
9410
+ products,
9411
+ renderCard,
9412
+ renderImage,
9413
+ renderLink,
9414
+ onQuickAdd,
9415
+ className
9150
9416
  }) {
9151
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-order-detail-page": true, className: cn(className, classNames?.root), children: [
9152
- /* @__PURE__ */ jsxs("div", { "data-cimplify-order-detail-header": true, className: classNames?.header, children: [
9153
- onBack && /* @__PURE__ */ jsx(
9154
- "button",
9417
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "featured", className: cn("space-y-10", className), children: [
9418
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-hero": true, className: "relative overflow-hidden rounded-2xl bg-muted", children: [
9419
+ collection.image_url && /* @__PURE__ */ jsx(
9420
+ "img",
9155
9421
  {
9156
- type: "button",
9157
- onClick: onBack,
9158
- "data-cimplify-order-detail-back": true,
9159
- className: classNames?.backButton,
9160
- children: backLabel
9422
+ src: collection.image_url,
9423
+ alt: collection.name,
9424
+ className: "w-full h-72 lg:h-96 object-cover"
9161
9425
  }
9162
9426
  ),
9163
- /* @__PURE__ */ jsx("h1", { "data-cimplify-order-detail-title": true, className: classNames?.title, children: "Order Details" })
9427
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent" }),
9428
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-8 lg:p-12", children: [
9429
+ collection.tags && collection.tags.length > 0 && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-white/70 uppercase tracking-widest", children: collection.tags[0] }),
9430
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl lg:text-5xl font-bold text-white tracking-tight mt-2", children: collection.name }),
9431
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-white/80 mt-3 max-w-2xl text-base lg:text-lg leading-relaxed", children: collection.description })
9432
+ ] })
9433
+ ] }),
9434
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: products.map(
9435
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9436
+ ProductCard,
9437
+ {
9438
+ product,
9439
+ renderImage,
9440
+ renderLink,
9441
+ onQuickAdd
9442
+ },
9443
+ product.id
9444
+ )
9445
+ ) })
9446
+ ] });
9447
+ }
9448
+ function CatalogueCollectionLayout({
9449
+ collection,
9450
+ products,
9451
+ renderCard,
9452
+ renderImage,
9453
+ renderLink,
9454
+ onQuickAdd,
9455
+ className
9456
+ }) {
9457
+ const [searchQuery, setSearchQuery] = useState("");
9458
+ const [activeCategory, setActiveCategory] = useState(null);
9459
+ const [sortBy, setSortBy] = useState("default");
9460
+ const categories = useMemo(() => {
9461
+ const cats = /* @__PURE__ */ new Map();
9462
+ for (const p of products) {
9463
+ if (p.category_id && p.tags) {
9464
+ for (const t of p.tags) {
9465
+ if (!cats.has(t)) cats.set(t, t);
9466
+ }
9467
+ }
9468
+ }
9469
+ return Array.from(cats.values()).slice(0, 8);
9470
+ }, [products]);
9471
+ const filtered = useMemo(() => {
9472
+ let result = products;
9473
+ if (searchQuery.trim().length >= 2) {
9474
+ const q = searchQuery.toLowerCase();
9475
+ result = result.filter(
9476
+ (p) => p.name.toLowerCase().includes(q) || p.description?.toLowerCase().includes(q)
9477
+ );
9478
+ }
9479
+ if (activeCategory) {
9480
+ result = result.filter((p) => p.tags?.includes(activeCategory));
9481
+ }
9482
+ if (sortBy === "price-asc") {
9483
+ result = [...result].sort((a, b) => parsePrice(a.default_price) - parsePrice(b.default_price));
9484
+ } else if (sortBy === "price-desc") {
9485
+ result = [...result].sort((a, b) => parsePrice(b.default_price) - parsePrice(a.default_price));
9486
+ } else if (sortBy === "name") {
9487
+ result = [...result].sort((a, b) => a.name.localeCompare(b.name));
9488
+ }
9489
+ return result;
9490
+ }, [products, searchQuery, activeCategory, sortBy]);
9491
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-collection-layout": "catalogue", className: cn("space-y-6", className), children: [
9492
+ /* @__PURE__ */ jsxs("div", { children: [
9493
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl lg:text-3xl font-bold tracking-tight", children: collection.name }),
9494
+ collection.description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 max-w-2xl", children: collection.description })
9495
+ ] }),
9496
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 pb-4 border-b border-border", children: [
9497
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 w-full", children: [
9498
+ /* @__PURE__ */ jsxs("div", { className: "relative flex-1 max-w-sm", children: [
9499
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9500
+ /* @__PURE__ */ jsx(
9501
+ "input",
9502
+ {
9503
+ type: "search",
9504
+ value: searchQuery,
9505
+ onChange: (e) => setSearchQuery(e.target.value),
9506
+ placeholder: "Search...",
9507
+ 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"
9508
+ }
9509
+ )
9510
+ ] }),
9511
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto scrollbar-hide", children: [
9512
+ /* @__PURE__ */ jsx(
9513
+ "button",
9514
+ {
9515
+ onClick: () => setActiveCategory(null),
9516
+ className: cn(
9517
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9518
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9519
+ ),
9520
+ children: "All"
9521
+ }
9522
+ ),
9523
+ categories.map((cat) => /* @__PURE__ */ jsx(
9524
+ "button",
9525
+ {
9526
+ onClick: () => setActiveCategory(activeCategory === cat ? null : cat),
9527
+ className: cn(
9528
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9529
+ activeCategory === cat ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9530
+ ),
9531
+ children: cat
9532
+ },
9533
+ cat
9534
+ ))
9535
+ ] })
9536
+ ] }),
9537
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 shrink-0", children: [
9538
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
9539
+ filtered.length,
9540
+ " items"
9541
+ ] }),
9542
+ /* @__PURE__ */ jsxs(
9543
+ "select",
9544
+ {
9545
+ value: sortBy,
9546
+ onChange: (e) => setSortBy(e.target.value),
9547
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none focus:ring-2 focus:ring-primary/20",
9548
+ children: [
9549
+ /* @__PURE__ */ jsx("option", { value: "default", children: "Sort: Default" }),
9550
+ /* @__PURE__ */ jsx("option", { value: "price-asc", children: "Price: Low to High" }),
9551
+ /* @__PURE__ */ jsx("option", { value: "price-desc", children: "Price: High to Low" }),
9552
+ /* @__PURE__ */ jsx("option", { value: "name", children: "Name: A-Z" })
9553
+ ]
9554
+ }
9555
+ )
9556
+ ] })
9557
+ ] }),
9558
+ filtered.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: filtered.map(
9559
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9560
+ ProductCard,
9561
+ {
9562
+ product,
9563
+ renderImage,
9564
+ renderLink,
9565
+ onQuickAdd
9566
+ },
9567
+ product.id
9568
+ )
9569
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
9570
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No products found." }),
9571
+ /* @__PURE__ */ jsx(
9572
+ "button",
9573
+ {
9574
+ onClick: () => {
9575
+ setSearchQuery("");
9576
+ setActiveCategory(null);
9577
+ },
9578
+ className: "text-sm font-medium text-primary mt-2 hover:underline",
9579
+ children: "Clear filters"
9580
+ }
9581
+ )
9582
+ ] })
9583
+ ] });
9584
+ }
9585
+ var CollectionTemplate = /* @__PURE__ */ ((CollectionTemplate2) => {
9586
+ CollectionTemplate2["Default"] = "default";
9587
+ CollectionTemplate2["Featured"] = "featured";
9588
+ CollectionTemplate2["Catalogue"] = "catalogue";
9589
+ return CollectionTemplate2;
9590
+ })(CollectionTemplate || {});
9591
+ var BUILT_IN_LAYOUTS4 = {
9592
+ ["default" /* Default */]: DefaultCollectionLayout,
9593
+ ["featured" /* Featured */]: FeaturedCollectionLayout,
9594
+ ["catalogue" /* Catalogue */]: CatalogueCollectionLayout
9595
+ };
9596
+ var LARGE_COLLECTION_THRESHOLD = 30;
9597
+ function resolveTemplateKey2(collection, productCount) {
9598
+ const metaTemplate = collection.metadata?.page_template;
9599
+ if (typeof metaTemplate === "string" && metaTemplate.trim()) {
9600
+ return metaTemplate.trim();
9601
+ }
9602
+ if (collection.tags?.includes("featured") || collection.metadata?.is_featured === true) {
9603
+ return "featured" /* Featured */;
9604
+ }
9605
+ if (productCount > LARGE_COLLECTION_THRESHOLD) {
9606
+ return "catalogue" /* Catalogue */;
9607
+ }
9608
+ return "default" /* Default */;
9609
+ }
9610
+ function resolveLayout2(collection, productCount, pages, templates) {
9611
+ if (pages?.[collection.slug]) {
9612
+ return pages[collection.slug];
9613
+ }
9614
+ const key = resolveTemplateKey2(collection, productCount);
9615
+ if (templates?.[key]) {
9616
+ return templates[key];
9617
+ }
9618
+ if (BUILT_IN_LAYOUTS4[key]) {
9619
+ return BUILT_IN_LAYOUTS4[key];
9620
+ }
9621
+ return DefaultCollectionLayout;
9622
+ }
9623
+ function CollectionPage({
9624
+ collectionId,
9625
+ collection: collectionProp,
9626
+ products: productsProp,
9627
+ pages,
9628
+ templates,
9629
+ renderCard,
9630
+ renderImage,
9631
+ renderLink,
9632
+ onQuickAdd,
9633
+ className,
9634
+ classNames
9635
+ }) {
9636
+ const resolvedId = collectionId || collectionProp?.slug || collectionProp?.id || "";
9637
+ const {
9638
+ collection: fetchedCollection,
9639
+ products: fetchedProducts,
9640
+ isLoading
9641
+ } = useCollection(collectionProp ? null : resolvedId, {
9642
+ enabled: !collectionProp && resolvedId.length > 0
9643
+ });
9644
+ const collection = collectionProp ?? fetchedCollection;
9645
+ const products = productsProp ?? fetchedProducts;
9646
+ if (isLoading && !collection) {
9647
+ return /* @__PURE__ */ jsx(
9648
+ "div",
9649
+ {
9650
+ "data-cimplify-collection-page": true,
9651
+ "aria-busy": "true",
9652
+ className: cn(className, classNames?.root, classNames?.loading),
9653
+ children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
9654
+ /* @__PURE__ */ jsx("div", { className: "h-64 lg:h-80 bg-muted rounded-2xl" }),
9655
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
9656
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
9657
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
9658
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
9659
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
9660
+ ] })
9661
+ ] }, i)) })
9662
+ ] })
9663
+ }
9664
+ );
9665
+ }
9666
+ if (!collection) {
9667
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Collection not found." }) });
9668
+ }
9669
+ const Layout = resolveLayout2(collection, products.length, pages, templates);
9670
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-collection-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
9671
+ Layout,
9672
+ {
9673
+ collection,
9674
+ products,
9675
+ renderCard,
9676
+ renderImage,
9677
+ renderLink,
9678
+ onQuickAdd
9679
+ }
9680
+ ) });
9681
+ }
9682
+ function OrderDetailPage({
9683
+ orderId,
9684
+ order,
9685
+ poll = true,
9686
+ onBack,
9687
+ renderLineItem,
9688
+ onReorder,
9689
+ onStatusChange,
9690
+ backLabel = "Back to orders",
9691
+ className,
9692
+ classNames
9693
+ }) {
9694
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-order-detail-page": true, className: cn(className, classNames?.root), children: [
9695
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-order-detail-header": true, className: classNames?.header, children: [
9696
+ onBack && /* @__PURE__ */ jsx(
9697
+ "button",
9698
+ {
9699
+ type: "button",
9700
+ onClick: onBack,
9701
+ "data-cimplify-order-detail-back": true,
9702
+ className: classNames?.backButton,
9703
+ children: backLabel
9704
+ }
9705
+ ),
9706
+ /* @__PURE__ */ jsx("h1", { "data-cimplify-order-detail-title": true, className: classNames?.title, children: "Order Details" })
9164
9707
  ] }),
9165
9708
  /* @__PURE__ */ jsx("div", { "data-cimplify-order-detail-content": true, className: classNames?.summary, children: /* @__PURE__ */ jsx(
9166
9709
  OrderSummary,
@@ -9253,573 +9796,355 @@ function OrderHistoryPage({
9253
9796
  ) })
9254
9797
  ] });
9255
9798
  }
9256
- function SearchPage({
9257
- title = "Search",
9258
- placeholder = "What are you looking for?",
9259
- onProductClick,
9799
+ function DefaultSearchLayout({
9800
+ search,
9801
+ facets,
9802
+ categories,
9803
+ activeCategory,
9804
+ onCategoryChange,
9805
+ inStockOnly,
9806
+ onInStockChange,
9807
+ sortBy,
9808
+ onSortChange,
9260
9809
  renderCard,
9261
9810
  renderImage,
9262
- columns,
9263
- className,
9264
- classNames
9811
+ renderLink,
9812
+ onQuickAdd,
9813
+ placeholder = "Search products...",
9814
+ className
9265
9815
  }) {
9266
- const { results, isLoading, query, setQuery, clear } = useSearch();
9267
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page": true, className: cn(className, classNames?.root), children: [
9268
- /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-search-page-title": true, className: classNames?.title, children: title }) }),
9269
- /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page-input": true, className: classNames?.inputContainer, children: [
9816
+ const { query, setQuery, results, isLoading, clear } = search;
9817
+ const hasFacets = facets && facets.length > 0 || categories && categories.length > 0;
9818
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-layout": "default", className: cn("space-y-6", className), children: [
9819
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
9820
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9270
9821
  /* @__PURE__ */ jsx(
9271
- Input,
9822
+ "input",
9272
9823
  {
9273
9824
  type: "search",
9274
9825
  value: query,
9275
9826
  onChange: (e) => setQuery(e.target.value),
9276
9827
  placeholder,
9277
- "data-cimplify-search-page-field": true,
9278
- className: classNames?.input,
9279
- "aria-label": "Search products",
9828
+ className: "w-full h-14 pl-12 pr-12 text-base border border-border rounded-xl bg-background outline-none focus:ring-2 focus:ring-primary/10 focus:border-primary/30 transition-all",
9280
9829
  autoFocus: true
9281
9830
  }
9282
9831
  ),
9283
9832
  query.length > 0 && /* @__PURE__ */ jsx(
9284
9833
  "button",
9285
9834
  {
9286
- type: "button",
9287
9835
  onClick: clear,
9288
- "data-cimplify-search-page-clear": true,
9289
- className: classNames?.clearButton,
9836
+ className: "absolute right-4 top-1/2 -translate-y-1/2 w-6 h-6 flex items-center justify-center text-muted-foreground hover:text-foreground rounded-full hover:bg-muted transition-colors",
9290
9837
  "aria-label": "Clear search",
9291
- children: "\xD7"
9838
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M6 18L18 6M6 6l12 12" }) })
9292
9839
  }
9293
9840
  )
9294
9841
  ] }),
9295
- query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("div", { "data-cimplify-search-page-count": true, className: classNames?.resultCount, children: [
9296
- results.length,
9297
- " ",
9298
- results.length === 1 ? "result" : "results",
9299
- " for \u201C",
9300
- query,
9301
- "\u201D"
9302
- ] }),
9303
- /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-grid": true, className: classNames?.grid, children: isLoading ? /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-loading": true, "aria-busy": "true", className: classNames?.loading, children: "Searching..." }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsx("div", { "data-cimplify-search-page-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsxs("p", { children: [
9304
- "No products found for \u201C",
9305
- query,
9306
- "\u201D"
9307
- ] }) }) : results.length > 0 && /* @__PURE__ */ jsx(
9308
- ProductGrid,
9309
- {
9310
- products: results,
9311
- renderCard,
9312
- renderImage,
9313
- columns
9314
- }
9315
- ) })
9316
- ] });
9317
- }
9318
- function DealsPage({
9319
- title = "Deals & Offers",
9320
- deals: dealsProp,
9321
- productsOnSale: productsOnSaleProp,
9322
- products: productsProp,
9323
- locationId,
9324
- renderImage,
9325
- columns,
9326
- className,
9327
- classNames
9328
- }) {
9329
- const { deals: fetchedDeals, isLoading: dealsLoading } = useDeals({
9330
- locationId,
9331
- enabled: dealsProp === void 0
9332
- });
9333
- const { products: fetchedOnSale, isLoading: productsLoading } = useProductsOnSale({
9334
- enabled: productsOnSaleProp === void 0
9335
- });
9336
- const deals = dealsProp ?? fetchedDeals;
9337
- const onSale = productsOnSaleProp ?? fetchedOnSale;
9338
- const isLoading = dealsLoading || productsLoading;
9339
- const isEmpty = deals.length === 0 && onSale.length === 0;
9340
- if (isLoading && isEmpty) {
9341
- return /* @__PURE__ */ jsx(
9342
- "div",
9343
- {
9344
- "data-cimplify-deals-page": true,
9345
- "aria-busy": "true",
9346
- className: cn(className, classNames?.root, classNames?.loading)
9347
- }
9348
- );
9349
- }
9350
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-page": true, className: cn(className, classNames?.root), children: [
9351
- /* @__PURE__ */ jsx("div", { "data-cimplify-deals-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-deals-title": true, className: classNames?.title, children: title }) }),
9352
- deals.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-banner-section": true, className: classNames?.bannerSection, children: /* @__PURE__ */ jsx(DealBanner, { deals }) }),
9353
- (onSale.length > 0 || productsProp && productsProp.length > 0) && /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-products": true, className: classNames?.productsSection, children: [
9354
- /* @__PURE__ */ jsx("h2", { "data-cimplify-deals-products-title": true, className: classNames?.productsTitle, children: "On Sale Now" }),
9355
- productsProp ? /* @__PURE__ */ jsx(
9356
- ProductGrid,
9842
+ query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9843
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
9844
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: results.length }),
9845
+ " result",
9846
+ results.length !== 1 ? "s" : "",
9847
+ " for ",
9848
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
9849
+ "\u201C",
9850
+ query,
9851
+ "\u201D"
9852
+ ] })
9853
+ ] }),
9854
+ onSortChange && /* @__PURE__ */ jsxs(
9855
+ "select",
9357
9856
  {
9358
- products: productsProp,
9359
- renderImage,
9360
- columns
9857
+ value: sortBy || "relevance",
9858
+ onChange: (e) => onSortChange(e.target.value),
9859
+ className: "text-xs border border-border rounded-lg px-2 py-1.5 bg-background outline-none focus:ring-2 focus:ring-primary/10",
9860
+ children: [
9861
+ /* @__PURE__ */ jsx("option", { value: "relevance", children: "Relevance" }),
9862
+ /* @__PURE__ */ jsx("option", { value: "price-asc", children: "Price: Low to High" }),
9863
+ /* @__PURE__ */ jsx("option", { value: "price-desc", children: "Price: High to Low" }),
9864
+ /* @__PURE__ */ jsx("option", { value: "name", children: "Name: A-Z" }),
9865
+ /* @__PURE__ */ jsx("option", { value: "newest", children: "Newest" })
9866
+ ]
9361
9867
  }
9362
- ) : /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-list": true, children: onSale.map((dealInfo) => /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-item": true, children: /* @__PURE__ */ jsx(
9363
- SaleBadge,
9868
+ )
9869
+ ] }),
9870
+ categories && categories.length > 0 && onCategoryChange && /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
9871
+ /* @__PURE__ */ jsx(
9872
+ "button",
9364
9873
  {
9365
- product: { id: dealInfo.product_id, name: dealInfo.deal_name },
9366
- dealInfo,
9367
- showOriginalPrice: true
9874
+ onClick: () => onCategoryChange(null),
9875
+ className: cn(
9876
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9877
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9878
+ ),
9879
+ children: "All"
9368
9880
  }
9369
- ) }, `${dealInfo.product_id}-${dealInfo.deal_id}`)) })
9881
+ ),
9882
+ categories.map((cat) => /* @__PURE__ */ jsx(
9883
+ "button",
9884
+ {
9885
+ onClick: () => onCategoryChange(activeCategory === cat.id ? null : cat.id),
9886
+ className: cn(
9887
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9888
+ activeCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9889
+ ),
9890
+ children: cat.name
9891
+ },
9892
+ cat.id
9893
+ ))
9370
9894
  ] }),
9371
- isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsx("p", { children: "No deals available right now. Check back soon!" }) })
9372
- ] });
9373
- }
9374
- var ANY_VALUE2 = "__any__";
9375
- function roomToResource(room) {
9376
- return {
9377
- id: room.id,
9378
- name: room.name,
9379
- capacity: room.capacity,
9380
- floor: room.floor,
9381
- is_available: room.status === "available"
9382
- };
9383
- }
9384
- function ResourcePicker({
9385
- resources,
9386
- selectedResourceId,
9387
- onResourceSelect,
9388
- showAnyOption = true,
9389
- anyLabel = "Any available",
9390
- renderImage,
9391
- className,
9392
- classNames
9393
- }) {
9394
- const groupValue = selectedResourceId === null ? ANY_VALUE2 : selectedResourceId ?? "";
9395
- return /* @__PURE__ */ jsxs(
9396
- RadioGroup,
9397
- {
9398
- "data-cimplify-resource-picker": true,
9399
- className: cn("flex flex-col gap-2", className, classNames?.root),
9400
- value: groupValue,
9401
- onValueChange: (value) => {
9402
- onResourceSelect?.(value === ANY_VALUE2 ? null : value);
9403
- },
9404
- children: [
9405
- showAnyOption && /* @__PURE__ */ jsx(
9406
- Radio.Root,
9407
- {
9408
- value: ANY_VALUE2,
9409
- "data-cimplify-resource-option": true,
9410
- "data-selected": selectedResourceId === null || void 0,
9411
- "data-any": true,
9412
- className: cn(
9413
- "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
9414
- "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
9415
- classNames?.option
9416
- ),
9417
- children: /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: anyLabel })
9418
- }
9419
- ),
9420
- resources.map((resource) => {
9421
- const unavailable = resource.is_available === false;
9422
- return /* @__PURE__ */ jsxs(
9423
- Radio.Root,
9895
+ /* @__PURE__ */ jsxs("div", { className: hasFacets ? "flex gap-6" : "", children: [
9896
+ hasFacets && /* @__PURE__ */ jsxs("aside", { "data-cimplify-search-facets": true, className: "hidden lg:block w-60 shrink-0 space-y-6", children: [
9897
+ onInStockChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
9898
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "In stock only" }),
9899
+ /* @__PURE__ */ jsx(
9900
+ "button",
9424
9901
  {
9425
- value: resource.id,
9426
- disabled: unavailable,
9427
- "data-cimplify-resource-option": true,
9428
- "data-selected": selectedResourceId === resource.id || void 0,
9429
- "data-unavailable": unavailable || void 0,
9902
+ onClick: () => onInStockChange(!inStockOnly),
9430
9903
  className: cn(
9431
- "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
9432
- "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
9433
- unavailable && "opacity-50 cursor-not-allowed",
9434
- classNames?.option,
9435
- unavailable ? classNames?.unavailable : void 0
9904
+ "w-10 h-6 rounded-full transition-colors relative",
9905
+ inStockOnly ? "bg-foreground" : "bg-border"
9436
9906
  ),
9437
- children: [
9438
- resource.image_url && (renderImage ? renderImage({
9439
- src: resource.image_url,
9440
- alt: resource.name,
9441
- className: classNames?.image
9442
- }) : /* @__PURE__ */ jsx(
9443
- "img",
9444
- {
9445
- src: resource.image_url,
9446
- alt: resource.name,
9447
- "data-cimplify-resource-image": true,
9448
- className: cn("w-10 h-10 rounded-lg object-cover", classNames?.image)
9449
- }
9450
- )),
9451
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 flex-1 min-w-0", children: [
9452
- /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: resource.name }),
9453
- resource.description && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-description": true, className: cn("text-sm text-muted-foreground truncate", classNames?.description), children: resource.description }),
9454
- /* @__PURE__ */ jsxs("div", { "data-cimplify-resource-meta": true, className: cn("flex items-center gap-2 text-xs text-muted-foreground", classNames?.meta), children: [
9455
- resource.capacity !== void 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-resource-capacity": true, className: classNames?.capacity, children: [
9456
- "Up to ",
9457
- resource.capacity
9458
- ] }),
9459
- resource.floor && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-floor": true, className: classNames?.floor, children: resource.floor })
9460
- ] })
9461
- ] })
9462
- ]
9463
- },
9464
- resource.id
9465
- );
9466
- })
9467
- ]
9468
- }
9469
- );
9470
- }
9471
- var STEP = {
9472
- SELECT_SLOT: "select-slot",
9473
- SELECT_RESOURCE: "select-resource",
9474
- SELECT_STAFF: "select-staff",
9475
- CONFIRM: "confirm"
9476
- };
9477
- function BookingPage({
9478
- service,
9479
- product,
9480
- staff,
9481
- resources,
9482
- participantCount,
9483
- title,
9484
- onBooked,
9485
- onBack,
9486
- existingBooking,
9487
- onRescheduled,
9488
- showPrice = true,
9489
- className,
9490
- classNames
9491
- }) {
9492
- const { addItem } = useCart();
9493
- const { client } = useCimplifyClient();
9494
- const isReschedule = existingBooking !== void 0;
9495
- const [step, setStep] = useState(STEP.SELECT_SLOT);
9496
- const [selectedSlot, setSelectedSlot] = useState(null);
9497
- const [selectedDate, setSelectedDate] = useState(null);
9498
- const [selectedStaffId, setSelectedStaffId] = useState(null);
9499
- const [selectedResourceId, setSelectedResourceId] = useState(null);
9500
- const [isSubmitting, setIsSubmitting] = useState(false);
9501
- const [error, setError] = useState(null);
9502
- const hasResourceStep = resources && resources.length > 0;
9503
- const hasStaffStep = staff && staff.length > 0;
9504
- const depositType = product?.deposit_type;
9505
- const depositAmount = product?.deposit_amount;
9506
- const hasDeposit = depositType !== void 0 && depositType !== "none" && depositAmount !== void 0 && parsePrice(depositAmount) !== 0;
9507
- const cancellationMinutes = product?.cancellation_window_minutes;
9508
- const noShowFee = product?.no_show_fee;
9509
- const handleSlotSelect = useCallback(
9510
- (slot, date) => {
9511
- setSelectedSlot(slot);
9512
- setSelectedDate(date);
9513
- setError(null);
9514
- if (hasResourceStep) {
9515
- setStep(STEP.SELECT_RESOURCE);
9516
- } else if (hasStaffStep) {
9517
- setStep(STEP.SELECT_STAFF);
9518
- } else {
9519
- setStep(STEP.CONFIRM);
9520
- }
9521
- },
9522
- [hasResourceStep, hasStaffStep]
9523
- );
9524
- const handleResourceSelect = useCallback(
9525
- (resourceId) => {
9526
- setSelectedResourceId(resourceId);
9527
- if (hasStaffStep) {
9528
- setStep(STEP.SELECT_STAFF);
9529
- } else {
9530
- setStep(STEP.CONFIRM);
9531
- }
9532
- },
9533
- [hasStaffStep]
9534
- );
9535
- const handleStaffSelect = useCallback((staffId) => {
9536
- setSelectedStaffId(staffId);
9537
- setStep(STEP.CONFIRM);
9538
- }, []);
9539
- const handleBack = useCallback(() => {
9540
- setError(null);
9541
- if (step === STEP.CONFIRM && hasStaffStep) {
9542
- setStep(STEP.SELECT_STAFF);
9543
- } else if (step === STEP.CONFIRM && hasResourceStep) {
9544
- setStep(STEP.SELECT_RESOURCE);
9545
- } else if (step === STEP.SELECT_STAFF && hasResourceStep) {
9546
- setStep(STEP.SELECT_RESOURCE);
9547
- } else if (step === STEP.CONFIRM || step === STEP.SELECT_STAFF || step === STEP.SELECT_RESOURCE) {
9548
- setStep(STEP.SELECT_SLOT);
9549
- } else {
9550
- onBack?.();
9551
- }
9552
- }, [step, hasStaffStep, hasResourceStep, onBack]);
9553
- const handleConfirm = useCallback(async () => {
9554
- if (!selectedSlot || !selectedDate) return;
9555
- setIsSubmitting(true);
9556
- setError(null);
9557
- try {
9558
- if (isReschedule && existingBooking) {
9559
- const serviceItem = existingBooking.service_items[0];
9560
- const result = await client.scheduling.rescheduleBooking({
9561
- order_id: existingBooking.order_id,
9562
- line_item_id: serviceItem?.service_id ?? existingBooking.order_id,
9563
- new_start_time: selectedSlot.start_time,
9564
- new_end_time: selectedSlot.end_time,
9565
- new_staff_id: selectedStaffId || void 0,
9566
- reschedule_type: "customer"
9567
- });
9568
- if (!result.ok) {
9569
- throw result.error;
9570
- }
9571
- onRescheduled?.(existingBooking, selectedSlot);
9572
- } else {
9573
- const serviceProduct = {
9574
- id: service.product_id || service.id,
9575
- business_id: service.business_id || "",
9576
- category_id: service.category_id || void 0,
9577
- name: service.name,
9578
- slug: service.id,
9579
- description: service.description || void 0,
9580
- image_url: service.image_url || void 0,
9581
- default_price: service.price || "0",
9582
- type: "service",
9583
- inventory_type: "none",
9584
- variant_strategy: "fetch_all",
9585
- is_active: service.is_available,
9586
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
9587
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
9588
- };
9589
- await addItem(serviceProduct, 1, {
9590
- scheduledStart: selectedSlot.start_time,
9591
- scheduledEnd: selectedSlot.end_time,
9592
- staffId: selectedStaffId || void 0,
9593
- resourceId: selectedResourceId || void 0
9594
- });
9595
- onBooked?.(selectedSlot, selectedStaffId);
9596
- }
9597
- } catch (err) {
9598
- const fallbackMessage = isReschedule ? "Failed to reschedule booking" : "Failed to add booking to cart";
9599
- setError(err instanceof Error ? err.message : fallbackMessage);
9600
- } finally {
9601
- setIsSubmitting(false);
9602
- }
9603
- }, [selectedSlot, selectedDate, selectedStaffId, service, addItem, onBooked, isReschedule, existingBooking, client, onRescheduled]);
9604
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page": true, className: cn(className, classNames?.root), children: [
9605
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-page-header": true, className: classNames?.header, children: [
9606
- onBack && step === STEP.SELECT_SLOT && /* @__PURE__ */ jsx(
9607
- "button",
9907
+ children: /* @__PURE__ */ jsx("span", { className: cn(
9908
+ "absolute top-1 w-4 h-4 rounded-full bg-background transition-transform shadow-sm",
9909
+ inStockOnly ? "left-5" : "left-1"
9910
+ ) })
9911
+ }
9912
+ )
9913
+ ] }),
9914
+ facets?.map((facet) => /* @__PURE__ */ jsxs("div", { children: [
9915
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: facet.name }),
9916
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: facet.values.slice(0, 8).map((fv) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm cursor-pointer group", children: [
9917
+ /* @__PURE__ */ jsx("input", { type: "checkbox", className: "w-3.5 h-3.5 accent-foreground rounded" }),
9918
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors flex-1", children: fv.value }),
9919
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground/60", children: fv.count })
9920
+ ] }, fv.value)) })
9921
+ ] }, facet.slug))
9922
+ ] }),
9923
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4 animate-pulse", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
9924
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
9925
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
9926
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
9927
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
9928
+ ] })
9929
+ ] }, i)) }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-20", children: [
9930
+ /* @__PURE__ */ jsx("svg", { className: "w-12 h-12 mx-auto text-muted-foreground/30", fill: "none", stroke: "currentColor", strokeWidth: "1", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9931
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-medium mt-4", children: [
9932
+ "No results for \u201C",
9933
+ query,
9934
+ "\u201D"
9935
+ ] }),
9936
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
9937
+ /* @__PURE__ */ jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
9938
+ ] }) : results.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: results.map(
9939
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
9940
+ ProductCard,
9941
+ {
9942
+ product,
9943
+ renderImage,
9944
+ renderLink,
9945
+ onQuickAdd
9946
+ },
9947
+ product.id
9948
+ )
9949
+ ) }) : null })
9950
+ ] })
9951
+ ] });
9952
+ }
9953
+ function CompactSearchLayout({
9954
+ search,
9955
+ categories,
9956
+ activeCategory,
9957
+ onCategoryChange,
9958
+ renderCard,
9959
+ renderImage,
9960
+ renderLink,
9961
+ onQuickAdd,
9962
+ placeholder = "Search menu...",
9963
+ className
9964
+ }) {
9965
+ const { query, setQuery, results, isLoading, clear } = search;
9966
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-search-layout": "compact", className: cn("space-y-6", className), children: [
9967
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
9968
+ /* @__PURE__ */ jsx("svg", { className: "absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-muted-foreground", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
9969
+ /* @__PURE__ */ jsx(
9970
+ "input",
9608
9971
  {
9609
- type: "button",
9610
- onClick: onBack,
9611
- "data-cimplify-booking-page-back": true,
9612
- className: classNames?.backButton,
9613
- children: "Back"
9972
+ type: "search",
9973
+ value: query,
9974
+ onChange: (e) => setQuery(e.target.value),
9975
+ placeholder,
9976
+ 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",
9977
+ autoFocus: true
9614
9978
  }
9615
9979
  ),
9616
- step !== STEP.SELECT_SLOT && /* @__PURE__ */ jsx(
9980
+ query.length > 0 && /* @__PURE__ */ jsx(
9617
9981
  "button",
9618
9982
  {
9619
- type: "button",
9620
- onClick: handleBack,
9621
- "data-cimplify-booking-page-back": true,
9622
- className: classNames?.backButton,
9623
- children: "Back"
9624
- }
9625
- ),
9626
- /* @__PURE__ */ jsx("h1", { "data-cimplify-booking-page-title": true, className: classNames?.title, children: title || (isReschedule ? "Reschedule Booking" : `Book ${service.name}`) })
9627
- ] }),
9628
- isReschedule && existingBooking && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-reschedule-info": true, className: classNames?.rescheduleInfo, children: /* @__PURE__ */ jsxs("span", { children: [
9629
- "Rescheduling booking from ",
9630
- new Date(existingBooking.service_items[0]?.scheduled_start ?? existingBooking.created_at).toLocaleDateString()
9631
- ] }) }),
9632
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-service-info": true, className: classNames?.serviceInfo, children: [
9633
- /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-name": true, children: service.name }),
9634
- /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-duration": true, children: formatDuration4(service.duration_minutes, service.duration_unit) }),
9635
- service.price && /* @__PURE__ */ jsx("span", { "data-cimplify-booking-service-price": true, children: /* @__PURE__ */ jsx(Price, { amount: service.price }) }),
9636
- hasDeposit && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-deposit-info": true, className: classNames?.depositInfo, children: [
9637
- "Deposit: ",
9638
- depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount })
9639
- ] }),
9640
- cancellationMinutes !== void 0 && cancellationMinutes > 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-cancellation-policy": true, className: classNames?.cancellationPolicy, children: [
9641
- "Free cancellation up to ",
9642
- cancellationMinutes >= 60 ? `${Math.floor(cancellationMinutes / 60)} hour${Math.floor(cancellationMinutes / 60) !== 1 ? "s" : ""}` : `${cancellationMinutes} minute${cancellationMinutes !== 1 ? "s" : ""}`,
9643
- " before"
9644
- ] }),
9645
- noShowFee !== void 0 && parsePrice(noShowFee) !== 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-booking-no-show-fee": true, className: classNames?.cancellationPolicy, children: [
9646
- "No-show fee: ",
9647
- /* @__PURE__ */ jsx(Price, { amount: noShowFee })
9648
- ] })
9649
- ] }),
9650
- error && /* @__PURE__ */ jsx("div", { "data-cimplify-booking-error": true, className: classNames?.error, children: error }),
9651
- step === STEP.SELECT_SLOT && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-slot", className: classNames?.step, children: [
9652
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Select a date & time" }),
9653
- /* @__PURE__ */ jsx(
9654
- DateSlotPicker,
9655
- {
9656
- serviceId: service.id,
9657
- participantCount,
9658
- selectedSlot,
9659
- onSlotSelect: handleSlotSelect,
9660
- showPrice
9983
+ onClick: clear,
9984
+ 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",
9985
+ "aria-label": "Clear search",
9986
+ children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M6 18L18 6M6 6l12 12" }) })
9661
9987
  }
9662
9988
  )
9663
9989
  ] }),
9664
- step === STEP.SELECT_RESOURCE && resources && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-resource", className: cn(classNames?.step, classNames?.resourceStep), children: [
9665
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Choose a room" }),
9990
+ categories && categories.length > 0 && onCategoryChange && /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 overflow-x-auto pb-1", children: [
9666
9991
  /* @__PURE__ */ jsx(
9667
- ResourcePicker,
9992
+ "button",
9668
9993
  {
9669
- resources,
9670
- selectedResourceId,
9671
- onResourceSelect: handleResourceSelect
9994
+ onClick: () => onCategoryChange(null),
9995
+ className: cn(
9996
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
9997
+ !activeCategory ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
9998
+ ),
9999
+ children: "All"
9672
10000
  }
9673
- )
9674
- ] }),
9675
- step === STEP.SELECT_STAFF && staff && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "select-staff", className: classNames?.step, children: [
9676
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Choose a provider" }),
9677
- /* @__PURE__ */ jsx(
9678
- StaffPicker,
10001
+ ),
10002
+ categories.map((cat) => /* @__PURE__ */ jsx(
10003
+ "button",
9679
10004
  {
9680
- staff,
9681
- selectedStaffId,
9682
- onStaffSelect: handleStaffSelect
9683
- }
9684
- )
10005
+ onClick: () => onCategoryChange(activeCategory === cat.id ? null : cat.id),
10006
+ className: cn(
10007
+ "text-xs font-medium px-3 py-1.5 rounded-full shrink-0 transition-colors",
10008
+ activeCategory === cat.id ? "bg-foreground text-background" : "bg-muted text-muted-foreground hover:bg-muted/80"
10009
+ ),
10010
+ children: cat.name
10011
+ },
10012
+ cat.id
10013
+ ))
9685
10014
  ] }),
9686
- step === STEP.CONFIRM && selectedSlot && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-step": "confirm", className: classNames?.step, children: [
9687
- /* @__PURE__ */ jsx("h2", { "data-cimplify-booking-step-title": true, className: classNames?.stepTitle, children: "Confirm your booking" }),
9688
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary": true, className: classNames?.summary, children: [
9689
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9690
- /* @__PURE__ */ jsx("span", { children: "Service" }),
9691
- /* @__PURE__ */ jsx("span", { children: service.name })
9692
- ] }),
9693
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9694
- /* @__PURE__ */ jsx("span", { children: "Date" }),
9695
- /* @__PURE__ */ jsx("span", { children: selectedDate })
9696
- ] }),
9697
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9698
- /* @__PURE__ */ jsx("span", { children: "Time" }),
9699
- /* @__PURE__ */ jsx("span", { children: new Date(selectedSlot.start_time).toLocaleTimeString(void 0, {
9700
- hour: "numeric",
9701
- minute: "2-digit"
9702
- }) })
9703
- ] }),
9704
- /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9705
- /* @__PURE__ */ jsx("span", { children: "Duration" }),
9706
- /* @__PURE__ */ jsx("span", { children: formatDuration4(service.duration_minutes, service.duration_unit) })
9707
- ] }),
9708
- selectedResourceId && resources && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9709
- /* @__PURE__ */ jsx("span", { children: "Room" }),
9710
- /* @__PURE__ */ jsx("span", { children: resources.find((r) => r.id === selectedResourceId)?.name ?? "Selected" })
9711
- ] }),
9712
- selectedStaffId && staff && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9713
- /* @__PURE__ */ jsx("span", { children: "Provider" }),
9714
- /* @__PURE__ */ jsx("span", { children: staff.find((s) => s.id === selectedStaffId)?.name ?? "Selected" })
9715
- ] }),
9716
- (selectedSlot.price || service.price) && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: classNames?.summaryRow, children: [
9717
- /* @__PURE__ */ jsx("span", { children: "Price" }),
9718
- /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(Price, { amount: selectedSlot.price || service.price }) })
9719
- ] }),
9720
- hasDeposit && /* @__PURE__ */ jsxs("div", { "data-cimplify-booking-summary-row": true, className: cn(classNames?.summaryRow, classNames?.depositInfo), children: [
9721
- /* @__PURE__ */ jsx("span", { children: "Deposit" }),
9722
- /* @__PURE__ */ jsx("span", { children: depositType === "percentage" ? `${parsePrice(depositAmount)}%` : /* @__PURE__ */ jsx(Price, { amount: depositAmount }) })
9723
- ] })
10015
+ query.length >= 2 && !isLoading && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
10016
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: results.length }),
10017
+ " result",
10018
+ results.length !== 1 ? "s" : "",
10019
+ " for ",
10020
+ /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
10021
+ "\u201C",
10022
+ query,
10023
+ "\u201D"
10024
+ ] })
10025
+ ] }),
10026
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-5 animate-pulse", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsxs("div", { children: [
10027
+ /* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted rounded-[14px]" }),
10028
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2", children: [
10029
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
10030
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
10031
+ ] })
10032
+ ] }, i)) }) : query.length >= 2 && results.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "text-center py-16", children: [
10033
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-medium", children: [
10034
+ "No results for \u201C",
10035
+ query,
10036
+ "\u201D"
9724
10037
  ] }),
9725
- /* @__PURE__ */ jsx(
9726
- "button",
10038
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1", children: "Try a different search term" }),
10039
+ /* @__PURE__ */ jsx("button", { onClick: clear, className: "text-sm font-medium text-primary mt-4 hover:underline", children: "Clear search" })
10040
+ ] }) : results.length > 0 ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-3 gap-5", children: results.map(
10041
+ (product) => renderCard ? /* @__PURE__ */ jsx(React3.Fragment, { children: renderCard(product) }, product.id) : /* @__PURE__ */ jsx(
10042
+ ProductCard,
9727
10043
  {
9728
- type: "button",
9729
- onClick: handleConfirm,
9730
- disabled: isSubmitting,
9731
- "data-cimplify-booking-confirm": true,
9732
- className: classNames?.confirmButton,
9733
- children: isSubmitting ? isReschedule ? "Rescheduling\u2026" : "Adding to cart\u2026" : isReschedule ? "Reschedule" : "Confirm Booking"
9734
- }
10044
+ product,
10045
+ renderImage,
10046
+ renderLink,
10047
+ onQuickAdd
10048
+ },
10049
+ product.id
9735
10050
  )
9736
- ] })
10051
+ ) }) : null
9737
10052
  ] });
9738
10053
  }
9739
- var BOOKING_FILTERS = [
9740
- { label: "All", value: "all" },
9741
- { label: "Upcoming", value: "upcoming" },
9742
- { label: "Past", value: "past" }
9743
- ];
9744
- function BookingsPage({
9745
- title = "My Bookings",
9746
- bookings: bookingsProp,
9747
- onBookingNavigate,
9748
- onCancel,
9749
- onReschedule,
9750
- showFilters = true,
9751
- renderBooking,
10054
+ var SearchTemplate = /* @__PURE__ */ ((SearchTemplate2) => {
10055
+ SearchTemplate2["Default"] = "default";
10056
+ SearchTemplate2["Compact"] = "compact";
10057
+ return SearchTemplate2;
10058
+ })(SearchTemplate || {});
10059
+ var BUILT_IN_LAYOUTS5 = {
10060
+ ["default" /* Default */]: DefaultSearchLayout,
10061
+ ["compact" /* Compact */]: CompactSearchLayout
10062
+ };
10063
+ function SearchPage({
10064
+ template,
10065
+ layouts,
10066
+ categories,
10067
+ facets,
10068
+ searchOptions,
10069
+ placeholder,
10070
+ renderCard,
10071
+ renderImage,
10072
+ renderLink,
10073
+ onQuickAdd,
9752
10074
  className,
9753
10075
  classNames
9754
10076
  }) {
9755
- const [filter, setFilter] = useState("all");
9756
- const [selectedBooking, setSelectedBooking] = useState(null);
9757
- const handleBookingClick = useCallback(
9758
- (booking) => {
9759
- if (onBookingNavigate) {
9760
- onBookingNavigate(booking);
9761
- } else {
9762
- setSelectedBooking(booking);
10077
+ const search = useSearch(searchOptions);
10078
+ const key = template ?? "default" /* Default */;
10079
+ const Layout = layouts?.[key] ?? BUILT_IN_LAYOUTS5[key] ?? DefaultSearchLayout;
10080
+ return /* @__PURE__ */ jsx("div", { "data-cimplify-search-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsx(
10081
+ Layout,
10082
+ {
10083
+ search,
10084
+ facets,
10085
+ categories,
10086
+ renderCard,
10087
+ renderImage,
10088
+ renderLink,
10089
+ onQuickAdd,
10090
+ placeholder
10091
+ }
10092
+ ) });
10093
+ }
10094
+ function DealsPage({
10095
+ title = "Deals & Offers",
10096
+ deals: dealsProp,
10097
+ productsOnSale: productsOnSaleProp,
10098
+ products: productsProp,
10099
+ locationId,
10100
+ renderImage,
10101
+ columns,
10102
+ className,
10103
+ classNames
10104
+ }) {
10105
+ const { deals: fetchedDeals, isLoading: dealsLoading } = useDeals({
10106
+ locationId,
10107
+ enabled: dealsProp === void 0
10108
+ });
10109
+ const { products: fetchedOnSale, isLoading: productsLoading } = useProductsOnSale({
10110
+ enabled: productsOnSaleProp === void 0
10111
+ });
10112
+ const deals = dealsProp ?? fetchedDeals;
10113
+ const onSale = productsOnSaleProp ?? fetchedOnSale;
10114
+ const isLoading = dealsLoading || productsLoading;
10115
+ const isEmpty = deals.length === 0 && onSale.length === 0;
10116
+ if (isLoading && isEmpty) {
10117
+ return /* @__PURE__ */ jsx(
10118
+ "div",
10119
+ {
10120
+ "data-cimplify-deals-page": true,
10121
+ "aria-busy": "true",
10122
+ className: cn(className, classNames?.root, classNames?.loading)
9763
10123
  }
9764
- },
9765
- [onBookingNavigate]
9766
- );
9767
- const handleBack = useCallback(() => {
9768
- setSelectedBooking(null);
9769
- }, []);
9770
- if (selectedBooking && !onBookingNavigate) {
9771
- return /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-page": true, className: cn(className, classNames?.root), children: /* @__PURE__ */ jsxs("div", { "data-cimplify-bookings-detail": true, className: classNames?.detail, children: [
9772
- /* @__PURE__ */ jsx(
9773
- "button",
10124
+ );
10125
+ }
10126
+ return /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-page": true, className: cn(className, classNames?.root), children: [
10127
+ /* @__PURE__ */ jsx("div", { "data-cimplify-deals-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-deals-title": true, className: classNames?.title, children: title }) }),
10128
+ deals.length > 0 && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-banner-section": true, className: classNames?.bannerSection, children: /* @__PURE__ */ jsx(DealBanner, { deals }) }),
10129
+ (onSale.length > 0 || productsProp && productsProp.length > 0) && /* @__PURE__ */ jsxs("div", { "data-cimplify-deals-products": true, className: classNames?.productsSection, children: [
10130
+ /* @__PURE__ */ jsx("h2", { "data-cimplify-deals-products-title": true, className: classNames?.productsTitle, children: "On Sale Now" }),
10131
+ productsProp ? /* @__PURE__ */ jsx(
10132
+ ProductGrid,
9774
10133
  {
9775
- type: "button",
9776
- onClick: handleBack,
9777
- "data-cimplify-bookings-back": true,
9778
- className: classNames?.backButton,
9779
- children: "Back to bookings"
10134
+ products: productsProp,
10135
+ renderImage,
10136
+ columns
9780
10137
  }
9781
- ),
9782
- /* @__PURE__ */ jsx(
9783
- BookingCard,
10138
+ ) : /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-list": true, children: onSale.map((dealInfo) => /* @__PURE__ */ jsx("div", { "data-cimplify-deals-sale-item": true, children: /* @__PURE__ */ jsx(
10139
+ SaleBadge,
9784
10140
  {
9785
- booking: selectedBooking,
9786
- onCancel,
9787
- onReschedule
10141
+ product: { id: dealInfo.product_id, name: dealInfo.deal_name },
10142
+ dealInfo,
10143
+ showOriginalPrice: true
9788
10144
  }
9789
- )
9790
- ] }) });
9791
- }
9792
- return /* @__PURE__ */ jsxs("div", { "data-cimplify-bookings-page": true, className: cn(className, classNames?.root), children: [
9793
- /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-header": true, className: classNames?.header, children: /* @__PURE__ */ jsx("h1", { "data-cimplify-bookings-title": true, className: classNames?.title, children: title }) }),
9794
- showFilters && /* @__PURE__ */ jsx(
9795
- Tabs.Root,
9796
- {
9797
- value: filter,
9798
- onValueChange: (value) => setFilter(value),
9799
- children: /* @__PURE__ */ jsx(Tabs.List, { "data-cimplify-bookings-filters": true, className: classNames?.filters, children: BOOKING_FILTERS.map((f) => /* @__PURE__ */ jsx(
9800
- Tabs.Tab,
9801
- {
9802
- value: f.value,
9803
- "data-cimplify-booking-filter": true,
9804
- "data-selected": filter === f.value || void 0,
9805
- className: classNames?.filterButton,
9806
- children: f.label
9807
- },
9808
- f.value
9809
- )) })
9810
- }
9811
- ),
9812
- /* @__PURE__ */ jsx("div", { "data-cimplify-bookings-list": true, className: classNames?.list, children: /* @__PURE__ */ jsx(
9813
- BookingList,
9814
- {
9815
- bookings: bookingsProp,
9816
- filter,
9817
- onCancel,
9818
- onReschedule,
9819
- onBookingClick: handleBookingClick,
9820
- renderBooking
9821
- }
9822
- ) })
10145
+ ) }, `${dealInfo.product_id}-${dealInfo.deal_id}`)) })
10146
+ ] }),
10147
+ isEmpty && /* @__PURE__ */ jsx("div", { "data-cimplify-deals-empty": true, className: classNames?.empty, children: /* @__PURE__ */ jsx("p", { children: "No deals available right now. Check back soon!" }) })
9823
10148
  ] });
9824
10149
  }
9825
10150
  function LocationPicker({
@@ -10180,5 +10505,102 @@ function CurrencySelector({
10180
10505
  );
10181
10506
  }) });
10182
10507
  }
10508
+ var ANY_VALUE2 = "__any__";
10509
+ function roomToResource(room) {
10510
+ return {
10511
+ id: room.id,
10512
+ name: room.name,
10513
+ capacity: room.capacity,
10514
+ floor: room.floor,
10515
+ is_available: room.status === "available"
10516
+ };
10517
+ }
10518
+ function ResourcePicker({
10519
+ resources,
10520
+ selectedResourceId,
10521
+ onResourceSelect,
10522
+ showAnyOption = true,
10523
+ anyLabel = "Any available",
10524
+ renderImage,
10525
+ className,
10526
+ classNames
10527
+ }) {
10528
+ const groupValue = selectedResourceId === null ? ANY_VALUE2 : selectedResourceId ?? "";
10529
+ return /* @__PURE__ */ jsxs(
10530
+ RadioGroup,
10531
+ {
10532
+ "data-cimplify-resource-picker": true,
10533
+ className: cn("flex flex-col gap-2", className, classNames?.root),
10534
+ value: groupValue,
10535
+ onValueChange: (value) => {
10536
+ onResourceSelect?.(value === ANY_VALUE2 ? null : value);
10537
+ },
10538
+ children: [
10539
+ showAnyOption && /* @__PURE__ */ jsx(
10540
+ Radio.Root,
10541
+ {
10542
+ value: ANY_VALUE2,
10543
+ "data-cimplify-resource-option": true,
10544
+ "data-selected": selectedResourceId === null || void 0,
10545
+ "data-any": true,
10546
+ className: cn(
10547
+ "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
10548
+ "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
10549
+ classNames?.option
10550
+ ),
10551
+ children: /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: anyLabel })
10552
+ }
10553
+ ),
10554
+ resources.map((resource) => {
10555
+ const unavailable = resource.is_available === false;
10556
+ return /* @__PURE__ */ jsxs(
10557
+ Radio.Root,
10558
+ {
10559
+ value: resource.id,
10560
+ disabled: unavailable,
10561
+ "data-cimplify-resource-option": true,
10562
+ "data-selected": selectedResourceId === resource.id || void 0,
10563
+ "data-unavailable": unavailable || void 0,
10564
+ className: cn(
10565
+ "flex items-center gap-3 rounded-lg border border-border p-3 transition-colors cursor-pointer",
10566
+ "hover:bg-muted data-[checked]:border-primary data-[checked]:bg-primary/5",
10567
+ unavailable && "opacity-50 cursor-not-allowed",
10568
+ classNames?.option,
10569
+ unavailable ? classNames?.unavailable : void 0
10570
+ ),
10571
+ children: [
10572
+ resource.image_url && (renderImage ? renderImage({
10573
+ src: resource.image_url,
10574
+ alt: resource.name,
10575
+ className: classNames?.image
10576
+ }) : /* @__PURE__ */ jsx(
10577
+ "img",
10578
+ {
10579
+ src: resource.image_url,
10580
+ alt: resource.name,
10581
+ "data-cimplify-resource-image": true,
10582
+ className: cn("w-10 h-10 rounded-lg object-cover", classNames?.image)
10583
+ }
10584
+ )),
10585
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 flex-1 min-w-0", children: [
10586
+ /* @__PURE__ */ jsx("span", { "data-cimplify-resource-name": true, className: cn("font-medium text-foreground", classNames?.name), children: resource.name }),
10587
+ resource.description && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-description": true, className: cn("text-sm text-muted-foreground truncate", classNames?.description), children: resource.description }),
10588
+ /* @__PURE__ */ jsxs("div", { "data-cimplify-resource-meta": true, className: cn("flex items-center gap-2 text-xs text-muted-foreground", classNames?.meta), children: [
10589
+ resource.capacity !== void 0 && /* @__PURE__ */ jsxs("span", { "data-cimplify-resource-capacity": true, className: classNames?.capacity, children: [
10590
+ "Up to ",
10591
+ resource.capacity
10592
+ ] }),
10593
+ resource.floor && /* @__PURE__ */ jsx("span", { "data-cimplify-resource-floor": true, className: classNames?.floor, children: resource.floor })
10594
+ ] })
10595
+ ] })
10596
+ ]
10597
+ },
10598
+ resource.id
10599
+ );
10600
+ })
10601
+ ]
10602
+ }
10603
+ );
10604
+ }
10183
10605
 
10184
- export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingsPage, BundleSelector, CardImage, CardShell, CardVariant, CartPage, CartSummary, CataloguePage, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyCheckout, CimplifyProvider, CollectionPage, CompactServiceCard, CompositeSelector, CurrencySelector, CustomAttributesTable, DateSlotPicker, DealBanner, DealsPage, DefaultProductLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, ServiceCard, ServiceGrid, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
10606
+ export { AccommodationCard, Ad, AdProvider, AddOnSelector, AddressElement, AuthElement, AvailabilityBadge, BillingPlanSelector, BookingCard, BookingList, BundleSelector, CardImage, CardShell, CardVariant, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, CheckoutPage, CimplifyAccount, CimplifyCheckout, CimplifyProvider, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeSelector, CurrencySelector, CustomAttributesTable, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, FeaturedCollectionLayout, FoodProductCard, FoodProductLayout, InventoryBadge, LeaseServiceCard, LocationPicker, MetadataStringList, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderSummary, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, SaleBadge, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, ServiceProductLayout, SessionMessageBanner, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, StoreNav, SubscriptionCard, TagPills, TwoColumnGrid, VariantSelector, VolumePricing, WholesaleProductCard, WholesaleProductLayout, WishlistButton, cn, roomToResource, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCategories, useCheckout, useCimplify, useCimplifyClient, useCollection, useCollections, useDeals, useDeliveryFee, useElements, useElementsReady, useFxRate, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };