@bailaya/react 1.0.25 → 1.0.26
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/components/ClassSchedule.d.ts +37 -10
- package/dist/components/ClassSchedule.d.ts.map +1 -1
- package/dist/components/ClassSchedule.js +76 -40
- package/dist/components/ClassScheduleByType.d.ts +39 -10
- package/dist/components/ClassScheduleByType.d.ts.map +1 -1
- package/dist/components/ClassScheduleByType.js +82 -41
- package/dist/styles.css +96 -0
- package/package.json +1 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type { StudioClass } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { StudioClass } from "@bailaya/core";
|
|
3
3
|
export interface ClassScheduleProps {
|
|
4
4
|
/** Optional start date for the 7-day window; defaults to today */
|
|
5
5
|
from?: Date;
|
|
6
6
|
/** Optional studio ID to override the default configured ID */
|
|
7
7
|
overrideId?: string;
|
|
8
|
-
/** Locale code for date formatting (e.g. "en", "es"); falls back to browser default */
|
|
8
|
+
/** Locale code for date/price formatting (e.g. "en", "es"); falls back to browser default */
|
|
9
9
|
locale?: string;
|
|
10
|
+
/** Currency code for price formatting (e.g., "USD", "MXN"). If omitted, shows decimal. */
|
|
11
|
+
currency?: string;
|
|
10
12
|
/** Custom labels (e.g. for "Instructor:" text) */
|
|
11
13
|
labels?: {
|
|
12
14
|
/** Label text for the instructor line; defaults to "Instructor:" */
|
|
@@ -16,25 +18,50 @@ export interface ClassScheduleProps {
|
|
|
16
18
|
className?: string;
|
|
17
19
|
/** Each class "card" wrapper */
|
|
18
20
|
itemClassName?: string;
|
|
21
|
+
/** Wrapper for the inner row (left/right) */
|
|
22
|
+
rowClassName?: string;
|
|
23
|
+
/** Left column (title/meta/instructor) */
|
|
24
|
+
leftClassName?: string;
|
|
19
25
|
/** Class name element */
|
|
20
26
|
nameClassName?: string;
|
|
27
|
+
/** Level element "(Beginner)" */
|
|
28
|
+
levelClassName?: string;
|
|
21
29
|
/** Details (date/time) element */
|
|
22
30
|
detailsClassName?: string;
|
|
23
31
|
/** Instructor line element */
|
|
24
32
|
instructorClassName?: string;
|
|
33
|
+
/** Right column container (price + button) */
|
|
34
|
+
rightClassName?: string;
|
|
35
|
+
/** Price element */
|
|
36
|
+
priceClassName?: string;
|
|
37
|
+
/** Button element */
|
|
38
|
+
buttonClassName?: string;
|
|
39
|
+
/** Text for the Book CTA (i18n). Default: "Book This Class" */
|
|
40
|
+
bookNowText?: string;
|
|
41
|
+
/** Base URL for booking links. Default: "https://www.bailaya.com/book/" */
|
|
42
|
+
bookBaseUrl?: string;
|
|
43
|
+
/** Hide the Book button entirely. Default: false */
|
|
44
|
+
hideBookButton?: boolean;
|
|
45
|
+
/** Custom price formatter (overrides `currency`) */
|
|
46
|
+
formatPrice?: (price: number, cls: StudioClass) => string;
|
|
25
47
|
/**
|
|
26
|
-
*
|
|
48
|
+
* Optional link renderer.
|
|
49
|
+
* If not provided, a plain <a> will be rendered.
|
|
27
50
|
*/
|
|
51
|
+
renderLink?: (opts: {
|
|
52
|
+
href: string;
|
|
53
|
+
className?: string;
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
}) => React.ReactNode;
|
|
56
|
+
/** Completely override the default renderItem */
|
|
28
57
|
renderItem?: (cls: StudioClass) => React.ReactNode;
|
|
29
58
|
}
|
|
30
59
|
/**
|
|
31
60
|
* Displays an upcoming-class schedule for a studio:
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* Uses sensible Tailwind defaults, but you can override
|
|
37
|
-
* every slot via props or replace the layout entirely.
|
|
61
|
+
* - name + level
|
|
62
|
+
* - weekday, date, time
|
|
63
|
+
* - optional instructor
|
|
64
|
+
* - RIGHT: price + "Book This Class" CTA
|
|
38
65
|
*/
|
|
39
66
|
export declare const ClassSchedule: React.FC<ClassScheduleProps>;
|
|
40
67
|
//# sourceMappingURL=ClassSchedule.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassSchedule.d.ts","sourceRoot":"","sources":["../../src/components/ClassSchedule.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ClassSchedule.d.ts","sourceRoot":"","sources":["../../src/components/ClassSchedule.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA4BjD,MAAM,WAAW,kBAAkB;IAC/B,kEAAkE;IAClE,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,kDAAkD;IAClD,MAAM,CAAC,EAAE;QACL,oEAAoE;QACpE,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,oDAAoD;IACpD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;IAE1D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;KAC7B,KAAK,KAAK,CAAC,SAAS,CAAC;IAEtB,iDAAiD;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,KAAK,CAAC,SAAS,CAAC;CACtD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6GtD,CAAC"}
|
|
@@ -8,58 +8,94 @@ exports.ClassSchedule = void 0;
|
|
|
8
8
|
const react_1 = __importDefault(require("react"));
|
|
9
9
|
const useClasses_1 = require("../hooks/useClasses");
|
|
10
10
|
const LoadingIcon_1 = require("./ui/LoadingIcon");
|
|
11
|
+
/** Default price formatter (uses currency if provided; falls back to decimal). */
|
|
12
|
+
function defaultFormatPrice(price, locale, currency) {
|
|
13
|
+
if (Number.isFinite(price)) {
|
|
14
|
+
if (currency) {
|
|
15
|
+
try {
|
|
16
|
+
return new Intl.NumberFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
17
|
+
style: "currency",
|
|
18
|
+
currency,
|
|
19
|
+
}).format(price);
|
|
20
|
+
}
|
|
21
|
+
catch (_a) {
|
|
22
|
+
/* ignore invalid currency and fall through */
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return new Intl.NumberFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
26
|
+
minimumFractionDigits: 2,
|
|
27
|
+
maximumFractionDigits: 2,
|
|
28
|
+
}).format(price);
|
|
29
|
+
}
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
11
32
|
/**
|
|
12
33
|
* Displays an upcoming-class schedule for a studio:
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Uses sensible Tailwind defaults, but you can override
|
|
18
|
-
* every slot via props or replace the layout entirely.
|
|
34
|
+
* - name + level
|
|
35
|
+
* - weekday, date, time
|
|
36
|
+
* - optional instructor
|
|
37
|
+
* - RIGHT: price + "Book This Class" CTA
|
|
19
38
|
*/
|
|
20
|
-
const ClassSchedule = ({ from, overrideId, locale, labels = {}, className =
|
|
39
|
+
const ClassSchedule = ({ from, overrideId, locale, currency, labels = {}, className = "by-scheduleList", itemClassName = "by-scheduleItem", rowClassName = "by-scheduleRow", leftClassName = "by-scheduleLeft", nameClassName = "by-scheduleName", levelClassName = "by-scheduleLevel", detailsClassName = "by-scheduleMeta", instructorClassName = "by-scheduleInstructor", rightClassName = "by-scheduleRight", priceClassName = "by-schedulePrice", buttonClassName = "by-btn by-btnBook", bookNowText = "Book This Class", bookBaseUrl = "https://www.bailaya.com/book/", hideBookButton = false, formatPrice, renderLink, renderItem, }) => {
|
|
21
40
|
var _a;
|
|
22
|
-
const { data: classes, loading
|
|
23
|
-
const weekdayFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale :
|
|
24
|
-
const dateFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale :
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
const { data: classes, loading, error } = (0, useClasses_1.useClasses)(from, overrideId);
|
|
42
|
+
const weekdayFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale : "en", { weekday: "long" });
|
|
43
|
+
const dateFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
44
|
+
month: "short",
|
|
45
|
+
day: "numeric",
|
|
46
|
+
});
|
|
47
|
+
const instructorLabel = (_a = labels === null || labels === void 0 ? void 0 : labels.instructor) !== null && _a !== void 0 ? _a : "Instructor:";
|
|
48
|
+
if (loading) {
|
|
49
|
+
return (react_1.default.createElement("ul", { className: className },
|
|
50
|
+
react_1.default.createElement("li", null,
|
|
51
|
+
react_1.default.createElement(LoadingIcon_1.LoadingIcon, null))));
|
|
29
52
|
}
|
|
30
53
|
if (error) {
|
|
31
|
-
return react_1.default.createElement("
|
|
54
|
+
return (react_1.default.createElement("ul", { className: className },
|
|
55
|
+
react_1.default.createElement("li", null, error.message)));
|
|
32
56
|
}
|
|
33
57
|
return (react_1.default.createElement("ul", { className: className }, classes === null || classes === void 0 ? void 0 : classes.map((cls) => {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const shortDate = dateFmt.format(dateObj);
|
|
58
|
+
const dayName = weekdayFmt.format(cls.date);
|
|
59
|
+
const shortDate = dateFmt.format(cls.date);
|
|
37
60
|
if (renderItem) {
|
|
38
61
|
return react_1.default.createElement("li", { key: cls.id }, renderItem(cls));
|
|
39
62
|
}
|
|
63
|
+
const priceText = formatPrice
|
|
64
|
+
? formatPrice(cls.price, cls)
|
|
65
|
+
: defaultFormatPrice(cls.price, locale, currency);
|
|
66
|
+
const href = `${bookBaseUrl}${cls.id}`;
|
|
40
67
|
return (react_1.default.createElement("li", { key: cls.id, className: itemClassName },
|
|
41
|
-
react_1.default.createElement("div",
|
|
42
|
-
react_1.default.createElement("div", { className:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
react_1.default.createElement("div", { className: rowClassName },
|
|
69
|
+
react_1.default.createElement("div", { className: leftClassName },
|
|
70
|
+
react_1.default.createElement("div", { className: nameClassName },
|
|
71
|
+
cls.name,
|
|
72
|
+
" ",
|
|
73
|
+
react_1.default.createElement("span", { className: levelClassName },
|
|
74
|
+
"(",
|
|
75
|
+
cls.level,
|
|
76
|
+
")")),
|
|
77
|
+
react_1.default.createElement("div", { className: detailsClassName },
|
|
78
|
+
dayName,
|
|
79
|
+
", ",
|
|
80
|
+
shortDate,
|
|
81
|
+
" \u2014 ",
|
|
82
|
+
cls.startTime,
|
|
83
|
+
"\u2013",
|
|
84
|
+
cls.endTime),
|
|
85
|
+
cls.instructor && (react_1.default.createElement("div", { className: instructorClassName },
|
|
86
|
+
instructorLabel,
|
|
87
|
+
" ",
|
|
88
|
+
react_1.default.createElement("strong", null,
|
|
89
|
+
cls.instructor.name,
|
|
90
|
+
cls.instructor.lastname ? ` ${cls.instructor.lastname}` : "")))),
|
|
91
|
+
react_1.default.createElement("div", { className: rightClassName },
|
|
92
|
+
Number.isFinite(cls.price) && (react_1.default.createElement("div", { className: priceClassName }, priceText)),
|
|
93
|
+
!hideBookButton &&
|
|
94
|
+
(renderLink ? (renderLink({
|
|
95
|
+
href,
|
|
96
|
+
className: buttonClassName,
|
|
97
|
+
children: bookNowText,
|
|
98
|
+
})) : (react_1.default.createElement("a", { href: href, className: buttonClassName }, bookNowText)))))));
|
|
63
99
|
})));
|
|
64
100
|
};
|
|
65
101
|
exports.ClassSchedule = ClassSchedule;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type { StudioClass } from
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { StudioClass } from "@bailaya/core";
|
|
3
3
|
export interface ClassScheduleByTypeProps {
|
|
4
4
|
/** The dance type to filter classes by (e.g., "salsa") */
|
|
5
5
|
typeName: string;
|
|
@@ -7,9 +7,11 @@ export interface ClassScheduleByTypeProps {
|
|
|
7
7
|
from?: Date;
|
|
8
8
|
/** Optional studio ID to override the default configured ID */
|
|
9
9
|
overrideId?: string;
|
|
10
|
-
/** Locale code for date formatting (e.g. "en", "es"); falls back to browser default */
|
|
10
|
+
/** Locale code for date/price formatting (e.g. "en", "es"); falls back to browser default */
|
|
11
11
|
locale?: string;
|
|
12
|
-
/**
|
|
12
|
+
/** Currency code for price formatting (e.g., "USD", "MXN"). If omitted, shows decimal. */
|
|
13
|
+
currency?: string;
|
|
14
|
+
/** Custom labels */
|
|
13
15
|
labels?: {
|
|
14
16
|
/** Label text for the instructor line; defaults to "Instructor:" */
|
|
15
17
|
instructor?: string;
|
|
@@ -18,12 +20,41 @@ export interface ClassScheduleByTypeProps {
|
|
|
18
20
|
className?: string;
|
|
19
21
|
/** Each class "card" wrapper */
|
|
20
22
|
itemClassName?: string;
|
|
23
|
+
/** Wrapper for the inner row (left/right) */
|
|
24
|
+
rowClassName?: string;
|
|
25
|
+
/** Left column (title/meta/instructor) */
|
|
26
|
+
leftClassName?: string;
|
|
21
27
|
/** Class name element */
|
|
22
28
|
nameClassName?: string;
|
|
29
|
+
/** Level element (the small, muted "(Beginner)" part) */
|
|
30
|
+
levelClassName?: string;
|
|
23
31
|
/** Details (date/time) element */
|
|
24
32
|
detailsClassName?: string;
|
|
25
33
|
/** Instructor line element */
|
|
26
34
|
instructorClassName?: string;
|
|
35
|
+
/** Right column container (price + button) */
|
|
36
|
+
rightClassName?: string;
|
|
37
|
+
/** Price element */
|
|
38
|
+
priceClassName?: string;
|
|
39
|
+
/** Button element */
|
|
40
|
+
buttonClassName?: string;
|
|
41
|
+
/** Text for the Book CTA (i18n). Default: "Book This Class" */
|
|
42
|
+
bookNowText?: string;
|
|
43
|
+
/** Base URL for booking links. Default: "https://www.bailaya.com/book/" */
|
|
44
|
+
bookBaseUrl?: string;
|
|
45
|
+
/** Hide the Book button entirely. Default: false */
|
|
46
|
+
hideBookButton?: boolean;
|
|
47
|
+
/** Custom price formatter (overrides `currency`) */
|
|
48
|
+
formatPrice?: (price: number, cls: StudioClass) => string;
|
|
49
|
+
/**
|
|
50
|
+
* Optional link renderer.
|
|
51
|
+
* If not provided, a plain <a> will be rendered.
|
|
52
|
+
*/
|
|
53
|
+
renderLink?: (opts: {
|
|
54
|
+
href: string;
|
|
55
|
+
className?: string;
|
|
56
|
+
children: React.ReactNode;
|
|
57
|
+
}) => React.ReactNode;
|
|
27
58
|
/**
|
|
28
59
|
* Completely override the default render for each item
|
|
29
60
|
*/
|
|
@@ -31,12 +62,10 @@ export interface ClassScheduleByTypeProps {
|
|
|
31
62
|
}
|
|
32
63
|
/**
|
|
33
64
|
* Displays a schedule of upcoming classes of a specific dance type:
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* Uses sensible Tailwind defaults but you can override
|
|
39
|
-
* every slot via props or bypass with renderItem.
|
|
65
|
+
* - name + level
|
|
66
|
+
* - weekday, date, time
|
|
67
|
+
* - optional instructor
|
|
68
|
+
* - RIGHT: price + "Book This Class" CTA
|
|
40
69
|
*/
|
|
41
70
|
export declare const ClassScheduleByType: React.FC<ClassScheduleByTypeProps>;
|
|
42
71
|
//# sourceMappingURL=ClassScheduleByType.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClassScheduleByType.d.ts","sourceRoot":"","sources":["../../src/components/ClassScheduleByType.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ClassScheduleByType.d.ts","sourceRoot":"","sources":["../../src/components/ClassScheduleByType.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA2BjD,MAAM,WAAW,wBAAwB;IACrC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IAEjB,kEAAkE;IAClE,IAAI,CAAC,EAAE,IAAI,CAAC;IAEZ,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oBAAoB;IACpB,MAAM,CAAC,EAAE;QACL,oEAAoE;QACpE,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8BAA8B;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,oDAAoD;IACpD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;IAE1D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;KAC7B,KAAK,KAAK,CAAC,SAAS,CAAC;IAEtB;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,KAAK,CAAC,SAAS,CAAC;CACtD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAgHlE,CAAC"}
|
|
@@ -7,31 +7,57 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.ClassScheduleByType = void 0;
|
|
8
8
|
const react_1 = __importDefault(require("react"));
|
|
9
9
|
const useClassesByType_1 = require("../hooks/useClassesByType");
|
|
10
|
+
/** Format price with optional currency or custom formatter */
|
|
11
|
+
function defaultFormatPrice(price, locale, currency) {
|
|
12
|
+
if (Number.isFinite(price)) {
|
|
13
|
+
if (currency) {
|
|
14
|
+
try {
|
|
15
|
+
return new Intl.NumberFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
16
|
+
style: "currency",
|
|
17
|
+
currency,
|
|
18
|
+
}).format(price);
|
|
19
|
+
}
|
|
20
|
+
catch (_a) {
|
|
21
|
+
// Fallback to decimal if currency code is invalid
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return new Intl.NumberFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
25
|
+
minimumFractionDigits: 2,
|
|
26
|
+
maximumFractionDigits: 2,
|
|
27
|
+
}).format(price);
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
10
31
|
/**
|
|
11
32
|
* Displays a schedule of upcoming classes of a specific dance type:
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* Uses sensible Tailwind defaults but you can override
|
|
17
|
-
* every slot via props or bypass with renderItem.
|
|
33
|
+
* - name + level
|
|
34
|
+
* - weekday, date, time
|
|
35
|
+
* - optional instructor
|
|
36
|
+
* - RIGHT: price + "Book This Class" CTA
|
|
18
37
|
*/
|
|
19
|
-
const ClassScheduleByType = ({ typeName, from, overrideId, locale, labels = {}, className =
|
|
38
|
+
const ClassScheduleByType = ({ typeName, from, overrideId, locale, currency, labels = {}, className = "by-scheduleList", itemClassName = "by-scheduleItem", rowClassName = "by-scheduleRow", leftClassName = "by-scheduleLeft", nameClassName = "by-scheduleName", levelClassName = "by-scheduleLevel", detailsClassName = "by-scheduleMeta", instructorClassName = "by-scheduleInstructor", rightClassName = "by-scheduleRight", priceClassName = "by-schedulePrice", buttonClassName = "by-btn by-btnBook", bookNowText = "Book This Class", bookBaseUrl = "https://www.bailaya.com/book/", hideBookButton = false, formatPrice, renderLink, renderItem, }) => {
|
|
20
39
|
var _a;
|
|
21
|
-
const { data: classes, loading
|
|
22
|
-
const weekdayFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale :
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
const { data: classes, loading, error } = (0, useClassesByType_1.useClassesByType)(typeName, from, overrideId);
|
|
41
|
+
const weekdayFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
42
|
+
weekday: "long",
|
|
43
|
+
});
|
|
44
|
+
const dateFmt = new Intl.DateTimeFormat(locale !== null && locale !== void 0 ? locale : "en", {
|
|
45
|
+
month: "short",
|
|
46
|
+
day: "numeric",
|
|
47
|
+
});
|
|
48
|
+
const instructorLabel = (_a = labels === null || labels === void 0 ? void 0 : labels.instructor) !== null && _a !== void 0 ? _a : "Instructor:";
|
|
49
|
+
if (loading) {
|
|
50
|
+
return react_1.default.createElement("ul", { className: className },
|
|
51
|
+
react_1.default.createElement("li", null,
|
|
52
|
+
"Loading ",
|
|
53
|
+
typeName,
|
|
54
|
+
" classes..."));
|
|
30
55
|
}
|
|
31
56
|
if (error) {
|
|
32
|
-
return react_1.default.createElement("
|
|
33
|
-
"
|
|
34
|
-
|
|
57
|
+
return react_1.default.createElement("ul", { className: className },
|
|
58
|
+
react_1.default.createElement("li", null,
|
|
59
|
+
"Error: ",
|
|
60
|
+
error.message));
|
|
35
61
|
}
|
|
36
62
|
return (react_1.default.createElement("ul", { className: className }, classes === null || classes === void 0 ? void 0 : classes.map((cls) => {
|
|
37
63
|
const dateObj = cls.date;
|
|
@@ -40,29 +66,44 @@ const ClassScheduleByType = ({ typeName, from, overrideId, locale, labels = {},
|
|
|
40
66
|
if (renderItem) {
|
|
41
67
|
return react_1.default.createElement("li", { key: cls.id }, renderItem(cls));
|
|
42
68
|
}
|
|
69
|
+
const priceText = formatPrice
|
|
70
|
+
? formatPrice(cls.price, cls)
|
|
71
|
+
: defaultFormatPrice(cls.price, locale, currency);
|
|
72
|
+
const href = `${bookBaseUrl}${cls.id}`;
|
|
43
73
|
return (react_1.default.createElement("li", { key: cls.id, className: itemClassName },
|
|
44
|
-
react_1.default.createElement("div",
|
|
45
|
-
react_1.default.createElement("div", { className:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
react_1.default.createElement("div", { className: rowClassName },
|
|
75
|
+
react_1.default.createElement("div", { className: leftClassName },
|
|
76
|
+
react_1.default.createElement("div", { className: nameClassName },
|
|
77
|
+
cls.name,
|
|
78
|
+
" ",
|
|
79
|
+
react_1.default.createElement("span", { className: levelClassName },
|
|
80
|
+
"(",
|
|
81
|
+
cls.level,
|
|
82
|
+
")")),
|
|
83
|
+
react_1.default.createElement("div", { className: detailsClassName },
|
|
84
|
+
weekday,
|
|
85
|
+
", ",
|
|
86
|
+
dateStr,
|
|
87
|
+
" \u2014 ",
|
|
88
|
+
cls.startTime,
|
|
89
|
+
"\u2013",
|
|
90
|
+
cls.endTime),
|
|
91
|
+
cls.instructor && (react_1.default.createElement("div", { className: instructorClassName },
|
|
92
|
+
instructorLabel,
|
|
93
|
+
" ",
|
|
94
|
+
react_1.default.createElement("strong", null,
|
|
95
|
+
cls.instructor.name,
|
|
96
|
+
cls.instructor.lastname
|
|
97
|
+
? ` ${cls.instructor.lastname}`
|
|
98
|
+
: "")))),
|
|
99
|
+
react_1.default.createElement("div", { className: rightClassName },
|
|
100
|
+
Number.isFinite(cls.price) && (react_1.default.createElement("div", { className: priceClassName }, priceText)),
|
|
101
|
+
!hideBookButton &&
|
|
102
|
+
(renderLink ? (renderLink({
|
|
103
|
+
href,
|
|
104
|
+
className: buttonClassName,
|
|
105
|
+
children: bookNowText,
|
|
106
|
+
})) : (react_1.default.createElement("a", { href: href, className: buttonClassName }, bookNowText)))))));
|
|
66
107
|
})));
|
|
67
108
|
};
|
|
68
109
|
exports.ClassScheduleByType = ClassScheduleByType;
|
package/dist/styles.css
CHANGED
|
@@ -217,3 +217,99 @@
|
|
|
217
217
|
font-size: 1.25rem;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
/* Container */
|
|
222
|
+
:where(.by-scheduleList) {
|
|
223
|
+
margin-top: 1.5rem;
|
|
224
|
+
display: flex;
|
|
225
|
+
flex-direction: column;
|
|
226
|
+
row-gap: 1rem;
|
|
227
|
+
}
|
|
228
|
+
@media (min-width: 768px) {
|
|
229
|
+
:where(.by-scheduleList) {
|
|
230
|
+
margin-top: 3rem;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Item card */
|
|
235
|
+
:where(.by-scheduleItem) {
|
|
236
|
+
padding: 1rem;
|
|
237
|
+
background: #fff;
|
|
238
|
+
border-radius: var(--by-radius-lg);
|
|
239
|
+
box-shadow: var(--by-shadow);
|
|
240
|
+
border: 1px solid var(--by-border);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Inner row: column on mobile; split left/right on md+ */
|
|
244
|
+
:where(.by-scheduleRow) {
|
|
245
|
+
display: flex;
|
|
246
|
+
flex-direction: column;
|
|
247
|
+
gap: 0.75rem;
|
|
248
|
+
}
|
|
249
|
+
@media (min-width: 768px) {
|
|
250
|
+
:where(.by-scheduleRow) {
|
|
251
|
+
flex-direction: row;
|
|
252
|
+
align-items: center;
|
|
253
|
+
justify-content: space-between;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Left column (title + meta + instructor) */
|
|
258
|
+
:where(.by-scheduleLeft) {
|
|
259
|
+
display: flex;
|
|
260
|
+
flex-direction: column;
|
|
261
|
+
min-width: 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* Title: name + level */
|
|
265
|
+
:where(.by-scheduleName) {
|
|
266
|
+
font-weight: 600;
|
|
267
|
+
font-size: 1.125rem;
|
|
268
|
+
color: var(--by-color-heading);
|
|
269
|
+
line-height: 1.2;
|
|
270
|
+
}
|
|
271
|
+
:where(.by-scheduleLevel) {
|
|
272
|
+
margin-left: 0.25rem;
|
|
273
|
+
font-size: 0.875rem;
|
|
274
|
+
opacity: 0.7;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/* Meta line: weekday, date, time */
|
|
278
|
+
:where(.by-scheduleMeta) {
|
|
279
|
+
color: var(--by-color-text);
|
|
280
|
+
font-size: 0.875rem;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* Instructor line */
|
|
284
|
+
:where(.by-scheduleInstructor) {
|
|
285
|
+
color: var(--by-color-text);
|
|
286
|
+
font-size: 0.875rem;
|
|
287
|
+
margin-top: 0.25rem;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* Right column: price + button */
|
|
291
|
+
:where(.by-scheduleRight) {
|
|
292
|
+
display: flex;
|
|
293
|
+
align-items: center;
|
|
294
|
+
gap: 1rem;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* Price style */
|
|
298
|
+
:where(.by-schedulePrice) {
|
|
299
|
+
font-weight: 700;
|
|
300
|
+
color: var(--by-color-heading);
|
|
301
|
+
font-size: 1rem;
|
|
302
|
+
}
|
|
303
|
+
@media (min-width: 768px) {
|
|
304
|
+
:where(.by-schedulePrice) {
|
|
305
|
+
font-size: 1.125rem;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* Button: reuse .by-btn base; adjust spacing for this layout */
|
|
310
|
+
:where(.by-btnBook) {
|
|
311
|
+
margin-top: 0; /* override .by-btn's margin if inherited elsewhere */
|
|
312
|
+
}
|
|
313
|
+
:where(.by-scheduleRight .by-btn) {
|
|
314
|
+
margin-top: 0;
|
|
315
|
+
}
|