@uptrademedia/site-kit 1.0.24 → 1.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +625 -588
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +625 -588
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1948,13 +1948,86 @@ function formatDuration(minutes) {
|
|
|
1948
1948
|
return `${hours}h ${mins}m`;
|
|
1949
1949
|
}
|
|
1950
1950
|
var DEFAULT_API_URL2 = "https://api.uptrademedia.com";
|
|
1951
|
+
var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1952
|
+
var MONTHS = [
|
|
1953
|
+
"January",
|
|
1954
|
+
"February",
|
|
1955
|
+
"March",
|
|
1956
|
+
"April",
|
|
1957
|
+
"May",
|
|
1958
|
+
"June",
|
|
1959
|
+
"July",
|
|
1960
|
+
"August",
|
|
1961
|
+
"September",
|
|
1962
|
+
"October",
|
|
1963
|
+
"November",
|
|
1964
|
+
"December"
|
|
1965
|
+
];
|
|
1966
|
+
function isSameDay(a, b) {
|
|
1967
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1968
|
+
}
|
|
1969
|
+
function isBeforeDay(a, b) {
|
|
1970
|
+
const ac = new Date(a.getFullYear(), a.getMonth(), a.getDate());
|
|
1971
|
+
const bc = new Date(b.getFullYear(), b.getMonth(), b.getDate());
|
|
1972
|
+
return ac < bc;
|
|
1973
|
+
}
|
|
1974
|
+
function calendarDays(year, month) {
|
|
1975
|
+
const first = new Date(year, month, 1);
|
|
1976
|
+
const last = new Date(year, month + 1, 0);
|
|
1977
|
+
const cells = [];
|
|
1978
|
+
for (let i = 0; i < first.getDay(); i++) cells.push(null);
|
|
1979
|
+
for (let d = 1; d <= last.getDate(); d++) cells.push(new Date(year, month, d));
|
|
1980
|
+
return cells;
|
|
1981
|
+
}
|
|
1982
|
+
function ChevronLeft() {
|
|
1983
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.5 15L7.5 10L12.5 5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1984
|
+
}
|
|
1985
|
+
function ChevronRight() {
|
|
1986
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 5L12.5 10L7.5 15", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1987
|
+
}
|
|
1988
|
+
function ClockIcon() {
|
|
1989
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1990
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1991
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4.5V8L10 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1992
|
+
] });
|
|
1993
|
+
}
|
|
1994
|
+
function GlobeIcon() {
|
|
1995
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
1996
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1997
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1.5 8H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
1998
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 1.5C9.66 3.34 10.61 5.62 10.61 8C10.61 10.38 9.66 12.66 8 14.5C6.34 12.66 5.39 10.38 5.39 8C5.39 5.62 6.34 3.34 8 1.5Z", stroke: "currentColor", strokeWidth: "1.2" })
|
|
1999
|
+
] });
|
|
2000
|
+
}
|
|
2001
|
+
function CheckCircleIcon() {
|
|
2002
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "56", height: "56", viewBox: "0 0 56 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2003
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "28", cy: "28", r: "28", fill: "var(--bw-primary)" }),
|
|
2004
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 28.5L24.5 35L38 21.5", stroke: "white", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
2005
|
+
] });
|
|
2006
|
+
}
|
|
2007
|
+
function CalendarPlusIcon() {
|
|
2008
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2009
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "1.5", y: "2.5", width: "13", height: "12", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
2010
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1.5 6.5H14.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
2011
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 1V4M11 1V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
|
|
2012
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 9V12M6.5 10.5H9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
|
|
2013
|
+
] });
|
|
2014
|
+
}
|
|
2015
|
+
function ArrowLeftIcon() {
|
|
2016
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8L10 13", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
2017
|
+
}
|
|
2018
|
+
function SpinnerIcon() {
|
|
2019
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "bw-spinner", children: [
|
|
2020
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "25", opacity: "0.3" }),
|
|
2021
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "50.265", strokeDashoffset: "37.7" })
|
|
2022
|
+
] });
|
|
2023
|
+
}
|
|
1951
2024
|
function BookingWidget({
|
|
1952
2025
|
orgSlug,
|
|
1953
2026
|
apiUrl = DEFAULT_API_URL2,
|
|
1954
2027
|
bookingTypeSlug,
|
|
1955
2028
|
timezone: propTimezone,
|
|
1956
2029
|
className = "",
|
|
1957
|
-
daysToShow =
|
|
2030
|
+
daysToShow = 60,
|
|
1958
2031
|
onBookingComplete,
|
|
1959
2032
|
onError,
|
|
1960
2033
|
hideTypeSelector = false,
|
|
@@ -1962,73 +2035,83 @@ function BookingWidget({
|
|
|
1962
2035
|
}) {
|
|
1963
2036
|
const [step, setStep] = React3.useState(bookingTypeSlug ? "datetime" : "type");
|
|
1964
2037
|
const [loading, setLoading] = React3.useState(false);
|
|
2038
|
+
const [slotsLoading, setSlotsLoading] = React3.useState(false);
|
|
1965
2039
|
const [error, setError] = React3.useState(null);
|
|
1966
2040
|
const [bookingTypes, setBookingTypes] = React3.useState([]);
|
|
1967
2041
|
const [selectedType, setSelectedType] = React3.useState(null);
|
|
2042
|
+
const [viewMonth, setViewMonth] = React3.useState(() => /* @__PURE__ */ new Date());
|
|
1968
2043
|
const [selectedDate, setSelectedDate] = React3.useState(null);
|
|
1969
2044
|
const [slots, setSlots] = React3.useState([]);
|
|
1970
2045
|
const [selectedSlot, setSelectedSlot] = React3.useState(null);
|
|
2046
|
+
const [confirmedSlot, setConfirmedSlot] = React3.useState(false);
|
|
1971
2047
|
const [hold, setHold] = React3.useState(null);
|
|
1972
2048
|
const [guestInfo, setGuestInfo] = React3.useState({ name: "", email: "" });
|
|
1973
2049
|
const [bookingResult, setBookingResult] = React3.useState(null);
|
|
2050
|
+
const [submitting, setSubmitting] = React3.useState(false);
|
|
2051
|
+
const slotsRef = React3.useRef(null);
|
|
2052
|
+
const today = React3.useMemo(() => {
|
|
2053
|
+
const d = /* @__PURE__ */ new Date();
|
|
2054
|
+
d.setHours(0, 0, 0, 0);
|
|
2055
|
+
return d;
|
|
2056
|
+
}, []);
|
|
1974
2057
|
const timezone = React3.useMemo(() => propTimezone || detectTimezone(), [propTimezone]);
|
|
1975
|
-
const
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
date.setDate(date.getDate() + i);
|
|
1982
|
-
if (date.getDay() !== 0 && date.getDay() !== 6) {
|
|
1983
|
-
dates.push(date);
|
|
1984
|
-
}
|
|
2058
|
+
const shortTz = React3.useMemo(() => {
|
|
2059
|
+
try {
|
|
2060
|
+
const parts = Intl.DateTimeFormat("en-US", { timeZone: timezone, timeZoneName: "short" }).formatToParts(/* @__PURE__ */ new Date());
|
|
2061
|
+
return parts.find((p) => p.type === "timeZoneName")?.value || timezone;
|
|
2062
|
+
} catch {
|
|
2063
|
+
return timezone;
|
|
1985
2064
|
}
|
|
1986
|
-
|
|
1987
|
-
|
|
2065
|
+
}, [timezone]);
|
|
2066
|
+
const days = React3.useMemo(() => calendarDays(viewMonth.getFullYear(), viewMonth.getMonth()), [viewMonth]);
|
|
2067
|
+
const maxDate = React3.useMemo(() => {
|
|
2068
|
+
const d = new Date(today);
|
|
2069
|
+
d.setDate(d.getDate() + daysToShow);
|
|
2070
|
+
return d;
|
|
2071
|
+
}, [today, daysToShow]);
|
|
1988
2072
|
React3.useEffect(() => {
|
|
1989
2073
|
if (bookingTypeSlug) {
|
|
2074
|
+
setLoading(true);
|
|
1990
2075
|
fetchBookingTypeDetails(orgSlug, bookingTypeSlug, apiUrl).then((type) => {
|
|
1991
2076
|
setSelectedType(type);
|
|
1992
2077
|
setStep("datetime");
|
|
1993
2078
|
}).catch((err) => {
|
|
1994
2079
|
setError(err.message);
|
|
1995
2080
|
onError?.(err);
|
|
1996
|
-
});
|
|
2081
|
+
}).finally(() => setLoading(false));
|
|
1997
2082
|
} else {
|
|
2083
|
+
setLoading(true);
|
|
1998
2084
|
fetchBookingTypes(orgSlug, apiUrl).then((types) => setBookingTypes(types.filter((t) => t.is_active))).catch((err) => {
|
|
1999
2085
|
setError(err.message);
|
|
2000
2086
|
onError?.(err);
|
|
2001
|
-
});
|
|
2087
|
+
}).finally(() => setLoading(false));
|
|
2002
2088
|
}
|
|
2003
2089
|
}, [orgSlug, bookingTypeSlug, apiUrl, onError]);
|
|
2004
2090
|
React3.useEffect(() => {
|
|
2005
2091
|
if (!selectedDate || !selectedType) return;
|
|
2006
2092
|
const dateStr = selectedDate.toISOString().split("T")[0];
|
|
2007
|
-
|
|
2093
|
+
setSlotsLoading(true);
|
|
2008
2094
|
setSlots([]);
|
|
2009
2095
|
setSelectedSlot(null);
|
|
2096
|
+
setConfirmedSlot(false);
|
|
2010
2097
|
fetchAvailability(orgSlug, selectedType.slug, dateStr, apiUrl, timezone).then((s) => setSlots(s.filter((slot) => slot.available))).catch((err) => {
|
|
2011
2098
|
setError(err.message);
|
|
2012
2099
|
onError?.(err);
|
|
2013
|
-
}).finally(() =>
|
|
2100
|
+
}).finally(() => setSlotsLoading(false));
|
|
2014
2101
|
}, [selectedDate, selectedType, orgSlug, apiUrl, timezone, onError]);
|
|
2015
|
-
const handleSlotSelect = React3.useCallback(
|
|
2016
|
-
if (!selectedType) return;
|
|
2017
|
-
if (hold) {
|
|
2018
|
-
await releaseSlotHold(hold.holdId, apiUrl).catch(() => {
|
|
2019
|
-
});
|
|
2020
|
-
}
|
|
2102
|
+
const handleSlotSelect = React3.useCallback((slot) => {
|
|
2021
2103
|
setSelectedSlot(slot);
|
|
2104
|
+
setConfirmedSlot(false);
|
|
2105
|
+
}, []);
|
|
2106
|
+
const handleSlotConfirm = React3.useCallback(async () => {
|
|
2107
|
+
if (!selectedType || !selectedSlot) return;
|
|
2108
|
+
if (hold) await releaseSlotHold(hold.holdId, apiUrl).catch(() => {
|
|
2109
|
+
});
|
|
2022
2110
|
setLoading(true);
|
|
2023
2111
|
try {
|
|
2024
|
-
const newHold = await createSlotHold(
|
|
2025
|
-
selectedType.id,
|
|
2026
|
-
slot.start,
|
|
2027
|
-
slot.hostId,
|
|
2028
|
-
timezone,
|
|
2029
|
-
apiUrl
|
|
2030
|
-
);
|
|
2112
|
+
const newHold = await createSlotHold(selectedType.id, selectedSlot.start, selectedSlot.hostId, timezone, apiUrl);
|
|
2031
2113
|
setHold(newHold);
|
|
2114
|
+
setConfirmedSlot(true);
|
|
2032
2115
|
setStep("form");
|
|
2033
2116
|
} catch (err) {
|
|
2034
2117
|
setError(err.message);
|
|
@@ -2036,22 +2119,14 @@ function BookingWidget({
|
|
|
2036
2119
|
} finally {
|
|
2037
2120
|
setLoading(false);
|
|
2038
2121
|
}
|
|
2039
|
-
}, [selectedType, hold, timezone, apiUrl, onError]);
|
|
2122
|
+
}, [selectedType, selectedSlot, hold, timezone, apiUrl, onError]);
|
|
2040
2123
|
const handleBookingSubmit = React3.useCallback(async (e) => {
|
|
2041
2124
|
e.preventDefault();
|
|
2042
2125
|
if (!selectedType || !selectedSlot) return;
|
|
2043
|
-
|
|
2126
|
+
setSubmitting(true);
|
|
2044
2127
|
setError(null);
|
|
2045
2128
|
try {
|
|
2046
|
-
const result = await createBooking(
|
|
2047
|
-
selectedType.id,
|
|
2048
|
-
selectedSlot.start,
|
|
2049
|
-
guestInfo,
|
|
2050
|
-
timezone,
|
|
2051
|
-
selectedSlot.hostId,
|
|
2052
|
-
hold?.holdId,
|
|
2053
|
-
apiUrl
|
|
2054
|
-
);
|
|
2129
|
+
const result = await createBooking(selectedType.id, selectedSlot.start, guestInfo, timezone, selectedSlot.hostId, hold?.holdId, apiUrl);
|
|
2055
2130
|
setBookingResult(result);
|
|
2056
2131
|
setStep("success");
|
|
2057
2132
|
onBookingComplete?.(result);
|
|
@@ -2059,577 +2134,539 @@ function BookingWidget({
|
|
|
2059
2134
|
setError(err.message);
|
|
2060
2135
|
onError?.(err);
|
|
2061
2136
|
} finally {
|
|
2062
|
-
|
|
2137
|
+
setSubmitting(false);
|
|
2063
2138
|
}
|
|
2064
2139
|
}, [selectedType, selectedSlot, guestInfo, timezone, hold, apiUrl, onBookingComplete, onError]);
|
|
2065
2140
|
React3.useEffect(() => {
|
|
2066
2141
|
return () => {
|
|
2067
|
-
if (hold) {
|
|
2068
|
-
|
|
2069
|
-
});
|
|
2070
|
-
}
|
|
2142
|
+
if (hold) releaseSlotHold(hold.holdId, apiUrl).catch(() => {
|
|
2143
|
+
});
|
|
2071
2144
|
};
|
|
2072
2145
|
}, [hold, apiUrl]);
|
|
2146
|
+
const canGoPrev = viewMonth.getFullYear() > today.getFullYear() || viewMonth.getMonth() > today.getMonth();
|
|
2147
|
+
const canGoNext = viewMonth < maxDate;
|
|
2148
|
+
const goMonth = (dir) => {
|
|
2149
|
+
setViewMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + dir, 1));
|
|
2150
|
+
};
|
|
2151
|
+
const groupedSlots = React3.useMemo(() => {
|
|
2152
|
+
const morning = [];
|
|
2153
|
+
const afternoon = [];
|
|
2154
|
+
const evening = [];
|
|
2155
|
+
for (const s of slots) {
|
|
2156
|
+
const h = new Date(s.start).getHours();
|
|
2157
|
+
if (h < 12) morning.push(s);
|
|
2158
|
+
else if (h < 17) afternoon.push(s);
|
|
2159
|
+
else evening.push(s);
|
|
2160
|
+
}
|
|
2161
|
+
return { morning, afternoon, evening };
|
|
2162
|
+
}, [slots]);
|
|
2073
2163
|
const cssVars = {
|
|
2074
|
-
"--
|
|
2075
|
-
"--
|
|
2076
|
-
"--
|
|
2164
|
+
"--bw-primary": styles2.primaryColor || "#0069ff",
|
|
2165
|
+
"--bw-primary-light": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 12%, white)` : "#e8f1ff",
|
|
2166
|
+
"--bw-primary-hover": styles2.primaryColor ? `color-mix(in srgb, ${styles2.primaryColor} 90%, black)` : "#0055d4",
|
|
2167
|
+
"--bw-radius": styles2.borderRadius || "8px",
|
|
2168
|
+
"--bw-font": styles2.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
2077
2169
|
};
|
|
2078
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2079
|
-
"div",
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
onClick: () => setSelectedDate(date),
|
|
2143
|
-
children: [
|
|
2144
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "uptrade-booking-date-day", children: date.toLocaleDateString("en-US", { weekday: "short" }) }),
|
|
2145
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "uptrade-booking-date-num", children: date.getDate() })
|
|
2146
|
-
]
|
|
2147
|
-
},
|
|
2148
|
-
dateStr
|
|
2149
|
-
);
|
|
2150
|
-
}) })
|
|
2170
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bw-root ${className}`, style: cssVars, children: [
|
|
2171
|
+
error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-error", role: "alert", children: [
|
|
2172
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: error }),
|
|
2173
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setError(null), "aria-label": "Dismiss error", children: "\xD7" })
|
|
2174
|
+
] }),
|
|
2175
|
+
step === "type" && !hideTypeSelector && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
2176
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "Select a Service" }),
|
|
2177
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
|
|
2178
|
+
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
|
|
2179
|
+
" Loading services..."
|
|
2180
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-type-list", children: bookingTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2181
|
+
"button",
|
|
2182
|
+
{
|
|
2183
|
+
className: "bw-type-card",
|
|
2184
|
+
onClick: () => {
|
|
2185
|
+
setSelectedType(type);
|
|
2186
|
+
setStep("datetime");
|
|
2187
|
+
},
|
|
2188
|
+
children: [
|
|
2189
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-type-name", children: type.name }),
|
|
2190
|
+
type.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-type-desc", children: type.description }),
|
|
2191
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-type-meta", children: [
|
|
2192
|
+
/* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
|
|
2193
|
+
" ",
|
|
2194
|
+
formatDuration(type.duration_minutes),
|
|
2195
|
+
type.price_cents ? ` \xB7 $${(type.price_cents / 100).toFixed(2)}` : " \xB7 Free"
|
|
2196
|
+
] })
|
|
2197
|
+
]
|
|
2198
|
+
},
|
|
2199
|
+
type.id
|
|
2200
|
+
)) })
|
|
2201
|
+
] }),
|
|
2202
|
+
step === "datetime" && selectedType && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
2203
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-info-header", children: [
|
|
2204
|
+
!bookingTypeSlug && /* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-back", onClick: () => {
|
|
2205
|
+
setSelectedType(null);
|
|
2206
|
+
setStep("type");
|
|
2207
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(ArrowLeftIcon, {}) }),
|
|
2208
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2209
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: selectedType.name }),
|
|
2210
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-meta-row", children: [
|
|
2211
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
|
|
2212
|
+
/* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
|
|
2213
|
+
" ",
|
|
2214
|
+
formatDuration(selectedType.duration_minutes)
|
|
2215
|
+
] }),
|
|
2216
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
|
|
2217
|
+
/* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, {}),
|
|
2218
|
+
" ",
|
|
2219
|
+
shortTz
|
|
2220
|
+
] })
|
|
2221
|
+
] })
|
|
2222
|
+
] })
|
|
2223
|
+
] }),
|
|
2224
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-datetime-layout", children: [
|
|
2225
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-calendar", children: [
|
|
2226
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-cal-header", children: [
|
|
2227
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(-1), disabled: !canGoPrev, "aria-label": "Previous month", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {}) }),
|
|
2228
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-cal-title", children: [
|
|
2229
|
+
MONTHS[viewMonth.getMonth()],
|
|
2230
|
+
" ",
|
|
2231
|
+
viewMonth.getFullYear()
|
|
2232
|
+
] }),
|
|
2233
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-cal-nav", onClick: () => goMonth(1), disabled: !canGoNext, "aria-label": "Next month", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {}) })
|
|
2151
2234
|
] }),
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2235
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-cal-weekdays", children: DAYS.map((d) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-cal-wd", children: d }, d)) }),
|
|
2236
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-cal-grid", children: days.map((date, i) => {
|
|
2237
|
+
if (!date) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-cal-empty" }, `e-${i}`);
|
|
2238
|
+
const past = isBeforeDay(date, today);
|
|
2239
|
+
const future = date > maxDate;
|
|
2240
|
+
const disabled = past || future;
|
|
2241
|
+
const sel = selectedDate && isSameDay(date, selectedDate);
|
|
2242
|
+
const isToday = isSameDay(date, today);
|
|
2243
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2155
2244
|
"button",
|
|
2156
2245
|
{
|
|
2157
|
-
className: `
|
|
2158
|
-
onClick: () =>
|
|
2159
|
-
disabled
|
|
2160
|
-
|
|
2246
|
+
className: `bw-cal-day${sel ? " selected" : ""}${isToday ? " today" : ""}${disabled ? " disabled" : ""}`,
|
|
2247
|
+
onClick: () => !disabled && setSelectedDate(date),
|
|
2248
|
+
disabled,
|
|
2249
|
+
"aria-label": date.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" }),
|
|
2250
|
+
"aria-pressed": sel || void 0,
|
|
2251
|
+
children: date.getDate()
|
|
2161
2252
|
},
|
|
2162
|
-
|
|
2163
|
-
)
|
|
2164
|
-
|
|
2253
|
+
date.toISOString()
|
|
2254
|
+
);
|
|
2255
|
+
}) })
|
|
2165
2256
|
] }),
|
|
2166
|
-
|
|
2167
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
selectedType.name,
|
|
2178
|
-
" on ",
|
|
2179
|
-
formatDate2(selectedSlot.start, timezone),
|
|
2180
|
-
" at ",
|
|
2181
|
-
formatTime(selectedSlot.start, timezone)
|
|
2257
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `bw-times${selectedDate ? " visible" : ""}`, ref: slotsRef, children: !selectedDate ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-times-placeholder", children: [
|
|
2258
|
+
/* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
|
|
2259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Select a date to view available times" })
|
|
2260
|
+
] }) : slotsLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
|
|
2261
|
+
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
|
|
2262
|
+
" Loading times..."
|
|
2263
|
+
] }) : slots.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-times-empty", children: "No available times on this date. Try another day." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-times-scroll", children: [
|
|
2264
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-times-date", children: selectedDate.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }) }),
|
|
2265
|
+
groupedSlots.morning.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
|
|
2266
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Morning" }),
|
|
2267
|
+
groupedSlots.morning.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2182
2268
|
] }),
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
" minutes"
|
|
2269
|
+
groupedSlots.afternoon.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
|
|
2270
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Afternoon" }),
|
|
2271
|
+
groupedSlots.afternoon.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2187
2272
|
] }),
|
|
2188
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
2189
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2190
|
-
|
|
2191
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2192
|
-
"input",
|
|
2193
|
-
{
|
|
2194
|
-
id: "guest-name",
|
|
2195
|
-
type: "text",
|
|
2196
|
-
required: true,
|
|
2197
|
-
value: guestInfo.name,
|
|
2198
|
-
onChange: (e) => setGuestInfo((prev) => ({ ...prev, name: e.target.value })),
|
|
2199
|
-
placeholder: "Your full name"
|
|
2200
|
-
}
|
|
2201
|
-
)
|
|
2202
|
-
] }),
|
|
2203
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
|
|
2204
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-email", children: "Email *" }),
|
|
2205
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2206
|
-
"input",
|
|
2207
|
-
{
|
|
2208
|
-
id: "guest-email",
|
|
2209
|
-
type: "email",
|
|
2210
|
-
required: true,
|
|
2211
|
-
value: guestInfo.email,
|
|
2212
|
-
onChange: (e) => setGuestInfo((prev) => ({ ...prev, email: e.target.value })),
|
|
2213
|
-
placeholder: "your@email.com"
|
|
2214
|
-
}
|
|
2215
|
-
)
|
|
2216
|
-
] }),
|
|
2217
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
|
|
2218
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-phone", children: "Phone" }),
|
|
2219
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2220
|
-
"input",
|
|
2221
|
-
{
|
|
2222
|
-
id: "guest-phone",
|
|
2223
|
-
type: "tel",
|
|
2224
|
-
value: guestInfo.phone || "",
|
|
2225
|
-
onChange: (e) => setGuestInfo((prev) => ({ ...prev, phone: e.target.value })),
|
|
2226
|
-
placeholder: "(555) 123-4567"
|
|
2227
|
-
}
|
|
2228
|
-
)
|
|
2229
|
-
] }),
|
|
2230
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "uptrade-booking-field", children: [
|
|
2231
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "guest-notes", children: "Additional Notes" }),
|
|
2232
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2233
|
-
"textarea",
|
|
2234
|
-
{
|
|
2235
|
-
id: "guest-notes",
|
|
2236
|
-
value: guestInfo.notes || "",
|
|
2237
|
-
onChange: (e) => setGuestInfo((prev) => ({ ...prev, notes: e.target.value })),
|
|
2238
|
-
placeholder: "Anything you'd like us to know...",
|
|
2239
|
-
rows: 3
|
|
2240
|
-
}
|
|
2241
|
-
)
|
|
2242
|
-
] }),
|
|
2243
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2244
|
-
"button",
|
|
2245
|
-
{
|
|
2246
|
-
type: "submit",
|
|
2247
|
-
className: "uptrade-booking-submit",
|
|
2248
|
-
disabled: loading,
|
|
2249
|
-
children: loading ? "Booking..." : "Confirm Booking"
|
|
2250
|
-
}
|
|
2251
|
-
)
|
|
2273
|
+
groupedSlots.evening.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-group", children: [
|
|
2274
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-label", children: "Evening" }),
|
|
2275
|
+
groupedSlots.evening.map((slot) => /* @__PURE__ */ jsxRuntime.jsx(TimeButton, { slot, selected: selectedSlot?.start === slot.start, confirmed: confirmedSlot && selectedSlot?.start === slot.start, onClick: () => handleSlotSelect(slot), onConfirm: handleSlotConfirm, timezone, loading }, slot.start))
|
|
2252
2276
|
] })
|
|
2253
|
-
] })
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2262
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
2263
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2264
|
-
" ",
|
|
2265
|
-
formatDate2(bookingResult.booking.scheduledAt, timezone),
|
|
2266
|
-
" at ",
|
|
2267
|
-
formatTime(bookingResult.booking.scheduledAt, timezone)
|
|
2268
|
-
] }),
|
|
2269
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
2270
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Duration:" }),
|
|
2277
|
+
] }) })
|
|
2278
|
+
] })
|
|
2279
|
+
] }),
|
|
2280
|
+
step === "form" && selectedType && selectedSlot && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in", children: [
|
|
2281
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-info-header", children: [
|
|
2282
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-back", onClick: () => setStep("datetime"), children: /* @__PURE__ */ jsxRuntime.jsx(ArrowLeftIcon, {}) }),
|
|
2283
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2284
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "Your Details" }),
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-meta-row", children: [
|
|
2286
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge", children: [
|
|
2287
|
+
/* @__PURE__ */ jsxRuntime.jsx(ClockIcon, {}),
|
|
2271
2288
|
" ",
|
|
2272
|
-
formatDuration(
|
|
2289
|
+
formatDuration(selectedType.duration_minutes)
|
|
2273
2290
|
] }),
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
" ",
|
|
2277
|
-
|
|
2291
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-badge-accent", children: [
|
|
2292
|
+
formatDate2(selectedSlot.start, timezone),
|
|
2293
|
+
" \xB7 ",
|
|
2294
|
+
formatTime(selectedSlot.start, timezone)
|
|
2278
2295
|
] })
|
|
2296
|
+
] })
|
|
2297
|
+
] })
|
|
2298
|
+
] }),
|
|
2299
|
+
hold && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-hold-notice", children: [
|
|
2300
|
+
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
|
|
2301
|
+
" Slot held for you \u2014 complete your details to confirm."
|
|
2302
|
+
] }),
|
|
2303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleBookingSubmit, className: "bw-form", children: [
|
|
2304
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
|
|
2305
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "bw-name", children: [
|
|
2306
|
+
"Name ",
|
|
2307
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-req", children: "*" })
|
|
2279
2308
|
] }),
|
|
2280
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
target: "_blank",
|
|
2298
|
-
rel: "noopener noreferrer",
|
|
2299
|
-
className: "uptrade-booking-calendar-btn",
|
|
2300
|
-
children: "Outlook"
|
|
2301
|
-
}
|
|
2302
|
-
),
|
|
2303
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2304
|
-
"a",
|
|
2305
|
-
{
|
|
2306
|
-
href: bookingResult.calendarLinks.ics,
|
|
2307
|
-
download: true,
|
|
2308
|
-
className: "uptrade-booking-calendar-btn",
|
|
2309
|
-
children: "Download .ics"
|
|
2310
|
-
}
|
|
2311
|
-
)
|
|
2312
|
-
] })
|
|
2309
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2310
|
+
"input",
|
|
2311
|
+
{
|
|
2312
|
+
id: "bw-name",
|
|
2313
|
+
type: "text",
|
|
2314
|
+
required: true,
|
|
2315
|
+
value: guestInfo.name,
|
|
2316
|
+
onChange: (e) => setGuestInfo((p) => ({ ...p, name: e.target.value })),
|
|
2317
|
+
placeholder: "Jane Smith",
|
|
2318
|
+
autoComplete: "name"
|
|
2319
|
+
}
|
|
2320
|
+
)
|
|
2321
|
+
] }),
|
|
2322
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
|
|
2323
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "bw-email", children: [
|
|
2324
|
+
"Email ",
|
|
2325
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-req", children: "*" })
|
|
2313
2326
|
] }),
|
|
2314
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2327
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2328
|
+
"input",
|
|
2329
|
+
{
|
|
2330
|
+
id: "bw-email",
|
|
2331
|
+
type: "email",
|
|
2332
|
+
required: true,
|
|
2333
|
+
value: guestInfo.email,
|
|
2334
|
+
onChange: (e) => setGuestInfo((p) => ({ ...p, email: e.target.value })),
|
|
2335
|
+
placeholder: "jane@example.com",
|
|
2336
|
+
autoComplete: "email"
|
|
2337
|
+
}
|
|
2338
|
+
)
|
|
2315
2339
|
] }),
|
|
2316
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
margin-bottom: 16px;
|
|
2496
|
-
}
|
|
2497
|
-
|
|
2498
|
-
.uptrade-booking-field {
|
|
2499
|
-
margin-bottom: 16px;
|
|
2500
|
-
}
|
|
2501
|
-
|
|
2502
|
-
.uptrade-booking-field label {
|
|
2503
|
-
display: block;
|
|
2504
|
-
margin-bottom: 4px;
|
|
2505
|
-
font-size: 0.875rem;
|
|
2506
|
-
font-weight: 500;
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
|
-
.uptrade-booking-field input,
|
|
2510
|
-
.uptrade-booking-field textarea {
|
|
2511
|
-
width: 100%;
|
|
2512
|
-
padding: 10px 12px;
|
|
2513
|
-
border: 1px solid #e5e5e5;
|
|
2514
|
-
border-radius: var(--booking-radius);
|
|
2515
|
-
font-size: 1rem;
|
|
2516
|
-
font-family: inherit;
|
|
2517
|
-
}
|
|
2518
|
-
|
|
2519
|
-
.uptrade-booking-field input:focus,
|
|
2520
|
-
.uptrade-booking-field textarea:focus {
|
|
2521
|
-
outline: none;
|
|
2522
|
-
border-color: var(--booking-primary);
|
|
2523
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--booking-primary) 15%, transparent);
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
|
-
.uptrade-booking-submit {
|
|
2527
|
-
width: 100%;
|
|
2528
|
-
padding: 14px;
|
|
2529
|
-
background: var(--booking-primary);
|
|
2530
|
-
color: #fff;
|
|
2531
|
-
border: none;
|
|
2532
|
-
border-radius: var(--booking-radius);
|
|
2533
|
-
font-size: 1rem;
|
|
2534
|
-
font-weight: 600;
|
|
2535
|
-
cursor: pointer;
|
|
2536
|
-
transition: opacity 0.2s;
|
|
2537
|
-
}
|
|
2538
|
-
|
|
2539
|
-
.uptrade-booking-submit:hover:not(:disabled) {
|
|
2540
|
-
opacity: 0.9;
|
|
2541
|
-
}
|
|
2542
|
-
|
|
2543
|
-
.uptrade-booking-submit:disabled {
|
|
2544
|
-
opacity: 0.5;
|
|
2545
|
-
cursor: not-allowed;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
.uptrade-booking-success {
|
|
2549
|
-
text-align: center;
|
|
2550
|
-
}
|
|
2551
|
-
|
|
2552
|
-
.uptrade-booking-success-icon {
|
|
2553
|
-
width: 64px;
|
|
2554
|
-
height: 64px;
|
|
2555
|
-
margin: 0 auto 16px;
|
|
2556
|
-
background: var(--booking-primary);
|
|
2557
|
-
color: #fff;
|
|
2558
|
-
border-radius: 50%;
|
|
2559
|
-
display: flex;
|
|
2560
|
-
align-items: center;
|
|
2561
|
-
justify-content: center;
|
|
2562
|
-
font-size: 2rem;
|
|
2563
|
-
}
|
|
2564
|
-
|
|
2565
|
-
.uptrade-booking-confirmation-code {
|
|
2566
|
-
font-family: monospace;
|
|
2567
|
-
background: #f5f5f5;
|
|
2568
|
-
padding: 8px 16px;
|
|
2569
|
-
border-radius: var(--booking-radius);
|
|
2570
|
-
display: inline-block;
|
|
2571
|
-
margin-bottom: 24px;
|
|
2572
|
-
}
|
|
2573
|
-
|
|
2574
|
-
.uptrade-booking-details {
|
|
2575
|
-
text-align: left;
|
|
2576
|
-
background: #f9f9f9;
|
|
2577
|
-
padding: 16px;
|
|
2578
|
-
border-radius: var(--booking-radius);
|
|
2579
|
-
margin-bottom: 24px;
|
|
2580
|
-
}
|
|
2581
|
-
|
|
2582
|
-
.uptrade-booking-details p {
|
|
2583
|
-
margin: 0 0 8px 0;
|
|
2584
|
-
}
|
|
2585
|
-
|
|
2586
|
-
.uptrade-booking-details p:last-child {
|
|
2587
|
-
margin-bottom: 0;
|
|
2588
|
-
}
|
|
2589
|
-
|
|
2590
|
-
.uptrade-booking-calendar-links {
|
|
2591
|
-
margin-bottom: 24px;
|
|
2592
|
-
}
|
|
2593
|
-
|
|
2594
|
-
.uptrade-booking-calendar-buttons {
|
|
2595
|
-
display: flex;
|
|
2596
|
-
gap: 8px;
|
|
2597
|
-
justify-content: center;
|
|
2598
|
-
margin-top: 8px;
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
.uptrade-booking-calendar-btn {
|
|
2602
|
-
padding: 8px 16px;
|
|
2603
|
-
border: 1px solid #e5e5e5;
|
|
2604
|
-
border-radius: var(--booking-radius);
|
|
2605
|
-
text-decoration: none;
|
|
2606
|
-
color: #333;
|
|
2607
|
-
font-size: 0.875rem;
|
|
2608
|
-
transition: all 0.2s;
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
.uptrade-booking-calendar-btn:hover {
|
|
2612
|
-
border-color: var(--booking-primary);
|
|
2613
|
-
color: var(--booking-primary);
|
|
2614
|
-
}
|
|
2615
|
-
|
|
2616
|
-
.uptrade-booking-email-notice {
|
|
2617
|
-
color: #666;
|
|
2618
|
-
font-size: 0.875rem;
|
|
2619
|
-
}
|
|
2620
|
-
|
|
2621
|
-
h4 {
|
|
2622
|
-
font-size: 0.875rem;
|
|
2623
|
-
font-weight: 600;
|
|
2624
|
-
margin: 0 0 12px 0;
|
|
2625
|
-
color: #666;
|
|
2626
|
-
}
|
|
2627
|
-
` })
|
|
2628
|
-
]
|
|
2629
|
-
}
|
|
2630
|
-
);
|
|
2340
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
|
|
2341
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "bw-phone", children: "Phone" }),
|
|
2342
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2343
|
+
"input",
|
|
2344
|
+
{
|
|
2345
|
+
id: "bw-phone",
|
|
2346
|
+
type: "tel",
|
|
2347
|
+
value: guestInfo.phone || "",
|
|
2348
|
+
onChange: (e) => setGuestInfo((p) => ({ ...p, phone: e.target.value })),
|
|
2349
|
+
placeholder: "(555) 123-4567",
|
|
2350
|
+
autoComplete: "tel"
|
|
2351
|
+
}
|
|
2352
|
+
)
|
|
2353
|
+
] }),
|
|
2354
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-field", children: [
|
|
2355
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "bw-notes", children: "Notes" }),
|
|
2356
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2357
|
+
"textarea",
|
|
2358
|
+
{
|
|
2359
|
+
id: "bw-notes",
|
|
2360
|
+
value: guestInfo.notes || "",
|
|
2361
|
+
onChange: (e) => setGuestInfo((p) => ({ ...p, notes: e.target.value })),
|
|
2362
|
+
placeholder: "Anything you'd like us to know...",
|
|
2363
|
+
rows: 3
|
|
2364
|
+
}
|
|
2365
|
+
)
|
|
2366
|
+
] }),
|
|
2367
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "bw-submit", disabled: submitting || !guestInfo.name || !guestInfo.email, children: submitting ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2368
|
+
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
|
|
2369
|
+
" Confirming..."
|
|
2370
|
+
] }) : "Confirm Booking" })
|
|
2371
|
+
] })
|
|
2372
|
+
] }),
|
|
2373
|
+
step === "success" && bookingResult && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-step bw-fade-in bw-success", children: [
|
|
2374
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bw-success-icon", children: /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, {}) }),
|
|
2375
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "bw-heading", children: "You\u2019re Booked!" }),
|
|
2376
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-conf-code", children: bookingResult.booking.confirmationCode }),
|
|
2377
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-details-card", children: [
|
|
2378
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
|
|
2379
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "When" }),
|
|
2380
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bw-detail-value", children: [
|
|
2381
|
+
formatDate2(bookingResult.booking.scheduledAt, timezone),
|
|
2382
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
2383
|
+
formatTime(bookingResult.booking.scheduledAt, timezone),
|
|
2384
|
+
" (",
|
|
2385
|
+
shortTz,
|
|
2386
|
+
")"
|
|
2387
|
+
] })
|
|
2388
|
+
] }),
|
|
2389
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
|
|
2390
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "Duration" }),
|
|
2391
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-value", children: formatDuration(bookingResult.booking.durationMinutes) })
|
|
2392
|
+
] }),
|
|
2393
|
+
bookingResult.booking.hostName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-detail-row", children: [
|
|
2394
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-label", children: "With" }),
|
|
2395
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-detail-value", children: bookingResult.booking.hostName })
|
|
2396
|
+
] })
|
|
2397
|
+
] }),
|
|
2398
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "bw-cal-links-label", children: "Add to your calendar" }),
|
|
2399
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-cal-links", children: [
|
|
2400
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.google, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
|
|
2401
|
+
/* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
|
|
2402
|
+
" Google"
|
|
2403
|
+
] }),
|
|
2404
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.outlook, target: "_blank", rel: "noopener noreferrer", className: "bw-cal-link", children: [
|
|
2405
|
+
/* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
|
|
2406
|
+
" Outlook"
|
|
2407
|
+
] }),
|
|
2408
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: bookingResult.calendarLinks.ics, download: true, className: "bw-cal-link", children: [
|
|
2409
|
+
/* @__PURE__ */ jsxRuntime.jsx(CalendarPlusIcon, {}),
|
|
2410
|
+
" iCal"
|
|
2411
|
+
] })
|
|
2412
|
+
] }),
|
|
2413
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "bw-email-notice", children: [
|
|
2414
|
+
"A confirmation email has been sent to ",
|
|
2415
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: guestInfo.email }),
|
|
2416
|
+
"."
|
|
2417
|
+
] })
|
|
2418
|
+
] }),
|
|
2419
|
+
loading && step === "datetime" && !selectedType && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-loading", children: [
|
|
2420
|
+
/* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}),
|
|
2421
|
+
" Loading..."
|
|
2422
|
+
] }),
|
|
2423
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: WIDGET_CSS })
|
|
2424
|
+
] });
|
|
2425
|
+
}
|
|
2426
|
+
function TimeButton({
|
|
2427
|
+
slot,
|
|
2428
|
+
selected,
|
|
2429
|
+
confirmed,
|
|
2430
|
+
onClick,
|
|
2431
|
+
onConfirm,
|
|
2432
|
+
timezone,
|
|
2433
|
+
loading
|
|
2434
|
+
}) {
|
|
2435
|
+
if (selected && !confirmed) {
|
|
2436
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bw-time-btn-wrap selected", children: [
|
|
2437
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bw-time-text", children: formatTime(slot.start, timezone) }),
|
|
2438
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "bw-time-confirm", onClick: onConfirm, disabled: loading, children: loading ? /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, {}) : "Confirm" })
|
|
2439
|
+
] });
|
|
2440
|
+
}
|
|
2441
|
+
return /* @__PURE__ */ jsxRuntime.jsx("button", { className: `bw-time-btn${selected ? " selected" : ""}`, onClick, disabled: loading, children: formatTime(slot.start, timezone) });
|
|
2442
|
+
}
|
|
2443
|
+
var WIDGET_CSS = `
|
|
2444
|
+
/* \u2500\u2500 Base \u2500\u2500 */
|
|
2445
|
+
.bw-root {
|
|
2446
|
+
font-family: var(--bw-font);
|
|
2447
|
+
color: #1a1a1a;
|
|
2448
|
+
line-height: 1.5;
|
|
2449
|
+
-webkit-font-smoothing: antialiased;
|
|
2450
|
+
box-sizing: border-box;
|
|
2451
|
+
}
|
|
2452
|
+
.bw-root *, .bw-root *::before, .bw-root *::after { box-sizing: border-box; }
|
|
2453
|
+
|
|
2454
|
+
/* \u2500\u2500 Animation \u2500\u2500 */
|
|
2455
|
+
@keyframes bw-fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
|
|
2456
|
+
@keyframes bw-spin { to { transform: rotate(360deg); } }
|
|
2457
|
+
.bw-fade-in { animation: bw-fade-in 0.25s ease-out; }
|
|
2458
|
+
.bw-spinner { animation: bw-spin 0.8s linear infinite; }
|
|
2459
|
+
|
|
2460
|
+
/* \u2500\u2500 Error \u2500\u2500 */
|
|
2461
|
+
.bw-error {
|
|
2462
|
+
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
2463
|
+
background: #fef2f2; border: 1px solid #fecaca; color: #b91c1c;
|
|
2464
|
+
padding: 10px 14px; border-radius: var(--bw-radius); margin-bottom: 16px; font-size: 0.875rem;
|
|
2465
|
+
}
|
|
2466
|
+
.bw-error button { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.25rem; line-height: 1; padding: 0; }
|
|
2467
|
+
|
|
2468
|
+
/* \u2500\u2500 Headings \u2500\u2500 */
|
|
2469
|
+
.bw-heading { font-size: 1.125rem; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
|
|
2470
|
+
.bw-meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
|
|
2471
|
+
.bw-badge {
|
|
2472
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
2473
|
+
font-size: 0.8125rem; color: #6b7280; font-weight: 400;
|
|
2474
|
+
}
|
|
2475
|
+
.bw-badge-accent {
|
|
2476
|
+
display: inline-flex; align-items: center; gap: 4px;
|
|
2477
|
+
font-size: 0.8125rem; color: var(--bw-primary); font-weight: 500;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
/* \u2500\u2500 Info Header \u2500\u2500 */
|
|
2481
|
+
.bw-info-header { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 20px; }
|
|
2482
|
+
.bw-back {
|
|
2483
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2484
|
+
width: 32px; height: 32px; border-radius: 50%; border: 1px solid #e5e7eb;
|
|
2485
|
+
background: #fff; cursor: pointer; color: #4b5563; flex-shrink: 0; margin-top: 1px;
|
|
2486
|
+
transition: all 0.15s;
|
|
2487
|
+
}
|
|
2488
|
+
.bw-back:hover { background: #f3f4f6; border-color: #d1d5db; }
|
|
2489
|
+
|
|
2490
|
+
/* \u2500\u2500 Loading \u2500\u2500 */
|
|
2491
|
+
.bw-loading {
|
|
2492
|
+
display: flex; align-items: center; justify-content: center; gap: 8px;
|
|
2493
|
+
padding: 32px; color: #6b7280; font-size: 0.875rem;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
/* \u2500\u2500 Type Selection \u2500\u2500 */
|
|
2497
|
+
.bw-type-list { display: flex; flex-direction: column; gap: 10px; }
|
|
2498
|
+
.bw-type-card {
|
|
2499
|
+
display: flex; flex-direction: column; text-align: left; gap: 4px;
|
|
2500
|
+
padding: 16px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2501
|
+
background: #fff; cursor: pointer; transition: all 0.15s;
|
|
2502
|
+
}
|
|
2503
|
+
.bw-type-card:hover { border-color: var(--bw-primary); box-shadow: 0 0 0 3px var(--bw-primary-light); }
|
|
2504
|
+
.bw-type-name { font-weight: 600; font-size: 0.9375rem; }
|
|
2505
|
+
.bw-type-desc { color: #6b7280; font-size: 0.8125rem; }
|
|
2506
|
+
.bw-type-meta { display: flex; align-items: center; gap: 4px; font-size: 0.8125rem; color: #9ca3af; margin-top: 4px; }
|
|
2507
|
+
|
|
2508
|
+
/* \u2500\u2500 Date-Time Layout \u2500\u2500 */
|
|
2509
|
+
.bw-datetime-layout {
|
|
2510
|
+
display: flex; gap: 0; border-top: 1px solid #f0f0f0; padding-top: 16px;
|
|
2511
|
+
}
|
|
2512
|
+
@media (max-width: 559px) {
|
|
2513
|
+
.bw-datetime-layout { flex-direction: column; }
|
|
2514
|
+
}
|
|
2515
|
+
@media (min-width: 560px) {
|
|
2516
|
+
.bw-datetime-layout { min-height: 340px; }
|
|
2517
|
+
.bw-calendar { flex: 1 1 auto; padding-right: 16px; border-right: 1px solid #f0f0f0; }
|
|
2518
|
+
.bw-times { width: 180px; flex-shrink: 0; padding-left: 16px; }
|
|
2631
2519
|
}
|
|
2632
2520
|
|
|
2521
|
+
/* \u2500\u2500 Calendar \u2500\u2500 */
|
|
2522
|
+
.bw-cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
|
|
2523
|
+
.bw-cal-title { font-weight: 600; font-size: 0.9375rem; }
|
|
2524
|
+
.bw-cal-nav {
|
|
2525
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
2526
|
+
width: 32px; height: 32px; border-radius: 50%; border: none;
|
|
2527
|
+
background: transparent; cursor: pointer; color: #374151; transition: background 0.15s;
|
|
2528
|
+
}
|
|
2529
|
+
.bw-cal-nav:hover:not(:disabled) { background: #f3f4f6; }
|
|
2530
|
+
.bw-cal-nav:disabled { opacity: 0.25; cursor: default; }
|
|
2531
|
+
|
|
2532
|
+
.bw-cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; text-align: center; margin-bottom: 4px; }
|
|
2533
|
+
.bw-cal-wd { font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; padding: 4px 0; }
|
|
2534
|
+
|
|
2535
|
+
.bw-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
|
|
2536
|
+
.bw-cal-empty { aspect-ratio: 1; }
|
|
2537
|
+
.bw-cal-day {
|
|
2538
|
+
aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
|
|
2539
|
+
border: none; background: none; border-radius: 50%;
|
|
2540
|
+
font-size: 0.8125rem; font-weight: 500; cursor: pointer;
|
|
2541
|
+
color: #1a1a1a; transition: all 0.15s; position: relative;
|
|
2542
|
+
}
|
|
2543
|
+
.bw-cal-day:hover:not(.disabled):not(.selected) { background: #f3f4f6; }
|
|
2544
|
+
.bw-cal-day.today:not(.selected)::after {
|
|
2545
|
+
content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
|
|
2546
|
+
width: 4px; height: 4px; border-radius: 50%; background: var(--bw-primary);
|
|
2547
|
+
}
|
|
2548
|
+
.bw-cal-day.selected {
|
|
2549
|
+
background: var(--bw-primary); color: #fff; font-weight: 600;
|
|
2550
|
+
}
|
|
2551
|
+
.bw-cal-day.disabled { color: #d1d5db; cursor: default; }
|
|
2552
|
+
|
|
2553
|
+
/* \u2500\u2500 Time Slots \u2500\u2500 */
|
|
2554
|
+
.bw-times { transition: opacity 0.2s; }
|
|
2555
|
+
.bw-times:not(.visible) { opacity: 0.5; }
|
|
2556
|
+
.bw-times.visible { opacity: 1; }
|
|
2557
|
+
.bw-times-placeholder {
|
|
2558
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
|
|
2559
|
+
height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
|
|
2560
|
+
}
|
|
2561
|
+
.bw-times-empty {
|
|
2562
|
+
display: flex; align-items: center; justify-content: center;
|
|
2563
|
+
height: 100%; min-height: 160px; color: #9ca3af; font-size: 0.8125rem; text-align: center; padding: 16px;
|
|
2564
|
+
}
|
|
2565
|
+
.bw-times-scroll { overflow-y: auto; max-height: 340px; }
|
|
2566
|
+
.bw-times-date { font-weight: 600; font-size: 0.8125rem; color: #374151; margin: 0 0 12px 0; }
|
|
2567
|
+
.bw-time-group { margin-bottom: 16px; }
|
|
2568
|
+
.bw-time-label { display: block; font-size: 0.6875rem; font-weight: 600; color: #9ca3af; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 6px; }
|
|
2569
|
+
|
|
2570
|
+
.bw-time-btn {
|
|
2571
|
+
display: block; width: 100%;
|
|
2572
|
+
padding: 10px 12px; margin-bottom: 6px;
|
|
2573
|
+
border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2574
|
+
background: #fff; cursor: pointer;
|
|
2575
|
+
font-size: 0.875rem; font-weight: 500; color: var(--bw-primary); text-align: center;
|
|
2576
|
+
transition: all 0.15s;
|
|
2577
|
+
}
|
|
2578
|
+
.bw-time-btn:hover:not(:disabled) {
|
|
2579
|
+
border-color: var(--bw-primary); background: var(--bw-primary-light);
|
|
2580
|
+
}
|
|
2581
|
+
.bw-time-btn.selected {
|
|
2582
|
+
border-color: var(--bw-primary); background: var(--bw-primary); color: #fff;
|
|
2583
|
+
}
|
|
2584
|
+
.bw-time-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
2585
|
+
|
|
2586
|
+
.bw-time-btn-wrap {
|
|
2587
|
+
display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
|
|
2588
|
+
border: 1.5px solid var(--bw-primary); border-radius: var(--bw-radius); overflow: hidden;
|
|
2589
|
+
animation: bw-fade-in 0.15s ease-out;
|
|
2590
|
+
}
|
|
2591
|
+
.bw-time-btn-wrap .bw-time-text {
|
|
2592
|
+
flex: 1; padding: 10px 12px; font-size: 0.875rem; font-weight: 500; color: #374151; text-align: center;
|
|
2593
|
+
background: var(--bw-primary-light);
|
|
2594
|
+
}
|
|
2595
|
+
.bw-time-confirm {
|
|
2596
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 4px;
|
|
2597
|
+
padding: 10px 16px; border: none;
|
|
2598
|
+
background: var(--bw-primary); color: #fff;
|
|
2599
|
+
font-size: 0.8125rem; font-weight: 600; cursor: pointer;
|
|
2600
|
+
transition: background 0.15s;
|
|
2601
|
+
}
|
|
2602
|
+
.bw-time-confirm:hover:not(:disabled) { background: var(--bw-primary-hover); }
|
|
2603
|
+
.bw-time-confirm:disabled { opacity: 0.7; cursor: not-allowed; }
|
|
2604
|
+
|
|
2605
|
+
/* \u2500\u2500 Form \u2500\u2500 */
|
|
2606
|
+
.bw-hold-notice {
|
|
2607
|
+
display: flex; align-items: center; gap: 8px;
|
|
2608
|
+
background: var(--bw-primary-light); color: var(--bw-primary);
|
|
2609
|
+
padding: 10px 14px; border-radius: var(--bw-radius);
|
|
2610
|
+
font-size: 0.8125rem; font-weight: 500; margin-bottom: 20px;
|
|
2611
|
+
}
|
|
2612
|
+
.bw-form { display: flex; flex-direction: column; gap: 16px; }
|
|
2613
|
+
.bw-field label {
|
|
2614
|
+
display: block; font-size: 0.8125rem; font-weight: 500; color: #374151; margin-bottom: 4px;
|
|
2615
|
+
}
|
|
2616
|
+
.bw-req { color: #ef4444; }
|
|
2617
|
+
.bw-field input, .bw-field textarea {
|
|
2618
|
+
display: block; width: 100%;
|
|
2619
|
+
padding: 10px 12px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2620
|
+
font-size: 0.9375rem; font-family: inherit; color: #1a1a1a; background: #fff;
|
|
2621
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
2622
|
+
}
|
|
2623
|
+
.bw-field input::placeholder, .bw-field textarea::placeholder { color: #c0c5cc; }
|
|
2624
|
+
.bw-field input:focus, .bw-field textarea:focus {
|
|
2625
|
+
outline: none; border-color: var(--bw-primary);
|
|
2626
|
+
box-shadow: 0 0 0 3px var(--bw-primary-light);
|
|
2627
|
+
}
|
|
2628
|
+
.bw-submit {
|
|
2629
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
|
2630
|
+
width: 100%; padding: 14px; margin-top: 4px;
|
|
2631
|
+
background: var(--bw-primary); color: #fff; border: none;
|
|
2632
|
+
border-radius: var(--bw-radius); font-size: 0.9375rem; font-weight: 600;
|
|
2633
|
+
cursor: pointer; transition: background 0.15s;
|
|
2634
|
+
}
|
|
2635
|
+
.bw-submit:hover:not(:disabled) { background: var(--bw-primary-hover); }
|
|
2636
|
+
.bw-submit:disabled { opacity: 0.55; cursor: not-allowed; }
|
|
2637
|
+
|
|
2638
|
+
/* \u2500\u2500 Success \u2500\u2500 */
|
|
2639
|
+
.bw-success { text-align: center; }
|
|
2640
|
+
.bw-success-icon { margin: 0 auto 16px; width: 56px; height: 56px; animation: bw-fade-in 0.4s ease-out; }
|
|
2641
|
+
.bw-conf-code {
|
|
2642
|
+
display: inline-block; font-family: 'SF Mono', 'Fira Code', monospace;
|
|
2643
|
+
background: #f3f4f6; padding: 6px 14px; border-radius: 6px;
|
|
2644
|
+
font-size: 0.8125rem; color: #6b7280; margin: 4px 0 20px; letter-spacing: 0.04em;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
.bw-details-card {
|
|
2648
|
+
text-align: left; background: #f9fafb; border: 1px solid #f0f0f0;
|
|
2649
|
+
border-radius: var(--bw-radius); padding: 16px; margin-bottom: 20px;
|
|
2650
|
+
}
|
|
2651
|
+
.bw-detail-row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
|
|
2652
|
+
.bw-detail-row:last-child { border-bottom: none; }
|
|
2653
|
+
.bw-detail-label { width: 70px; flex-shrink: 0; font-size: 0.8125rem; color: #9ca3af; font-weight: 500; }
|
|
2654
|
+
.bw-detail-value { font-size: 0.875rem; font-weight: 500; color: #374151; }
|
|
2655
|
+
|
|
2656
|
+
.bw-cal-links-label { font-size: 0.8125rem; color: #6b7280; margin: 0 0 8px 0; }
|
|
2657
|
+
.bw-cal-links { display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; flex-wrap: wrap; }
|
|
2658
|
+
.bw-cal-link {
|
|
2659
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
2660
|
+
padding: 8px 14px; border: 1.5px solid #e5e7eb; border-radius: var(--bw-radius);
|
|
2661
|
+
text-decoration: none; color: #374151; font-size: 0.8125rem; font-weight: 500;
|
|
2662
|
+
transition: all 0.15s;
|
|
2663
|
+
}
|
|
2664
|
+
.bw-cal-link:hover { border-color: var(--bw-primary); color: var(--bw-primary); }
|
|
2665
|
+
|
|
2666
|
+
.bw-email-notice { font-size: 0.8125rem; color: #9ca3af; margin: 0; }
|
|
2667
|
+
.bw-email-notice strong { color: #374151; font-weight: 500; }
|
|
2668
|
+
`;
|
|
2669
|
+
|
|
2633
2670
|
Object.defineProperty(exports, "TestimonialSection", {
|
|
2634
2671
|
enumerable: true,
|
|
2635
2672
|
get: function () { return chunkUJQ73OS6_js.TestimonialSection; }
|