@reblu/site-blocks 0.23.0 → 0.25.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/CHANGELOG.md +26 -0
- package/README.md +56 -6
- package/dist/index.cjs +418 -328
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +416 -328
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @reblu/site-blocks
|
|
2
2
|
|
|
3
|
+
## 0.25.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1860554: New `CoursePurchaseTerms`: the drop-in for what a buyer must see before paying for a course (REB-1199). It shows the withdrawal waiver, the access duration and the refund guarantee from `AcademyCourseDetail`. Each term renders only when the course carries it; with none, nothing renders. It is a Server Component. The default copy is Spanish and can be replaced with `labels`. Also exports `DEFAULT_COURSE_PURCHASE_TERMS_LABELS`.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [1860554]
|
|
12
|
+
- Updated dependencies [82ab415]
|
|
13
|
+
- @reblu/site-contracts@1.25.0
|
|
14
|
+
|
|
15
|
+
## 0.24.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- c7f3a43: Course catalogue filters are tenant config (REB-1234).
|
|
20
|
+
- `@reblu/site-contracts`: new `AcademyConfigPublic` and `AcademyCatalogFiltersPublic` types for `GET /api/site/academy/config`.
|
|
21
|
+
- `@reblu/site-client`: new `client.academy.config()`, returning `{ catalogFilters: { category, instructor, price } }` as switched on in nexus. A filter the tenant never set is `true`.
|
|
22
|
+
- `@reblu/site-blocks`: `CourseCatalogFilters` gains a category filter (`categories` + `hrefs.category`, `active.category`) and an `enabled` prop. Pass `catalogFilters` as `enabled` and only the switched-on filters render; with all off it renders nothing. Without `enabled` and `categories` the output is unchanged.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [c7f3a43]
|
|
27
|
+
- @reblu/site-contracts@1.24.0
|
|
28
|
+
|
|
3
29
|
## 0.23.0
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -25,11 +25,12 @@ colour on the red background. See `docs/theming/theming.md`.
|
|
|
25
25
|
| `sanitizeHtml` | `.` | Sanitises an HTML string before `dangerouslySetInnerHTML` — the **HTML boundary**. See "Security boundaries" below. |
|
|
26
26
|
| `MarkdownRenderer` | `.` | Canonical Blog renderer: `marked` → **hast-util-sanitize** (XSS) → component map, with a YouTube-domain allowlist. RSC-safe. |
|
|
27
27
|
| `CourseDescription` | `.` | Drop-in for the rich-text course `description` (`client.academy.bySlug()`). Server Component. See "Rich-text descriptions". |
|
|
28
|
+
| `CoursePurchaseTerms`, `DEFAULT_COURSE_PURCHASE_TERMS_LABELS` | `.` | What the buyer sees before paying: withdrawal waiver, access duration, refund guarantee. Server Component. See "Course purchase terms". |
|
|
28
29
|
| `LessonPreview`, `DEFAULT_LESSON_PREVIEW_LABELS` | `.` | A public free-preview lesson: hosted video player + sanitised body (`getLessonPreview()`). Server Component. See "Free-preview lesson". |
|
|
29
30
|
| `Treatment`, `ParentPage`, `ProfileCard`, `ProductCard` | `.` | Presentational organisms over the SITE API contracts. RSC-safe. `Specialty`: deprecated alias, see below. |
|
|
30
31
|
| `ProfessionalFields` | `.` | The tenant's own professional fields (`professional.fields`) on a team card or profile. RSC-safe. See below. |
|
|
31
32
|
| `ShopFilters` | `.` | Plug-and-play shop filter chrome over `GET /api/site/shop/facets`. RSC-safe. See "Shop filters" below. |
|
|
32
|
-
| `CourseCatalogFilters`, `DEFAULT_COURSE_PRICE_BANDS` | `.` | Course catalogue filters by instructor and price (`client.academy.
|
|
33
|
+
| `CourseCatalogFilters`, `DEFAULT_COURSE_PRICE_BANDS` | `.` | Course catalogue filters by category, instructor and price, each switchable per tenant (`client.academy.config()`). RSC-safe. See "Course catalogue filters". |
|
|
33
34
|
| `CartLineList`, `CartSummary`, `CartAdjustmentsNotice`, `AddedToCartToast`, `CheckoutLoginPrompt`, `CheckoutForm`, `OrderConfirmation` | `.` | Cart & checkout organisms. RSC-safe by construction. See "Cart & checkout" below. |
|
|
34
35
|
| `PageBlocks`, `FaqAccordion` | `.` | Registry-block renderer (`PageDetail.blocks`) and native `<details>` FAQ. Server Components. See "Page blocks" below. |
|
|
35
36
|
| `ProductTrustItems`, `DEFAULT_TRUST_ICONS` | `.` | Store-wide trust messages from `ShopConfig.productTrustItems`. Server Component. See "Product trust items" below. |
|
|
@@ -991,13 +992,19 @@ import { CourseSyllabus } from '@reblu/site-blocks/client'
|
|
|
991
992
|
and `course-syllabus-preview`. No slot was renamed in REB-1135. It renders
|
|
992
993
|
nothing for a course without modules.
|
|
993
994
|
|
|
994
|
-
## Course catalogue filters — `CourseCatalogFilters` (REB-547)
|
|
995
|
+
## Course catalogue filters — `CourseCatalogFilters` (REB-547, REB-1234)
|
|
995
996
|
|
|
996
|
-
Drop-in filters for the academy catalogue:
|
|
997
|
+
Drop-in filters for the academy catalogue: a category filter fed by
|
|
998
|
+
`client.academy.categories()`, an instructor filter fed by
|
|
997
999
|
`client.academy.instructors()` (instructors of published courses, sorted by
|
|
998
1000
|
name) and a price filter (bands in integer cents plus «Gratis»). Each option
|
|
999
|
-
maps 1:1 onto a `client.academy.courses()` param: `
|
|
1000
|
-
`priceMax`, `free`.
|
|
1001
|
+
maps 1:1 onto a `client.academy.courses()` param: `category`, `instructor`,
|
|
1002
|
+
`priceMin`, `priceMax`, `free`.
|
|
1003
|
+
|
|
1004
|
+
Which filters show is the tenant's choice, made in nexus › Formación ›
|
|
1005
|
+
Configuración › «Filtros del catálogo» and served by `client.academy.config()`
|
|
1006
|
+
as `catalogFilters`. Pass it as `enabled`: the component renders only the
|
|
1007
|
+
filters switched on, with no SITE code change when the tenant flips one. Same RSC-safe contract as `ShopFilters`: every option is a
|
|
1001
1008
|
real `<a href>`; pass `onChange` only from a `'use client'` boundary.
|
|
1002
1009
|
|
|
1003
1010
|
```tsx
|
|
@@ -1013,14 +1020,17 @@ export default async function CoursesPage({
|
|
|
1013
1020
|
const sp = await searchParams
|
|
1014
1021
|
const num = (v?: string) => (v ? Number(v) : undefined)
|
|
1015
1022
|
const active: AcademyCourseListQuery = {
|
|
1023
|
+
category: sp.category,
|
|
1016
1024
|
instructor: sp.instructor,
|
|
1017
1025
|
priceMin: num(sp.priceMin),
|
|
1018
1026
|
priceMax: num(sp.priceMax),
|
|
1019
1027
|
free: sp.free === 'true',
|
|
1020
1028
|
}
|
|
1021
|
-
const [courses, instructors] = await Promise.all([
|
|
1029
|
+
const [courses, categories, instructors, academy] = await Promise.all([
|
|
1022
1030
|
client.academy.courses(active),
|
|
1031
|
+
client.academy.categories(),
|
|
1023
1032
|
client.academy.instructors(),
|
|
1033
|
+
client.academy.config(),
|
|
1024
1034
|
])
|
|
1025
1035
|
|
|
1026
1036
|
// Keep the other params; `free` and a price band exclude each other.
|
|
@@ -1035,10 +1045,14 @@ export default async function CoursesPage({
|
|
|
1035
1045
|
|
|
1036
1046
|
return (
|
|
1037
1047
|
<>
|
|
1048
|
+
{/* Your search box stays: it is not a switchable filter. */}
|
|
1038
1049
|
<CourseCatalogFilters
|
|
1050
|
+
enabled={academy.catalogFilters}
|
|
1051
|
+
categories={categories.data}
|
|
1039
1052
|
instructors={instructors.data}
|
|
1040
1053
|
active={active}
|
|
1041
1054
|
hrefs={{
|
|
1055
|
+
category: (slug) => href({ category: slug }),
|
|
1042
1056
|
instructor: (id) => href({ instructor: id }),
|
|
1043
1057
|
price: (min, max) => href({ priceMin: min, priceMax: max, free: false }),
|
|
1044
1058
|
free: (next) => href({ free: next, priceMin: undefined, priceMax: undefined }),
|
|
@@ -1051,6 +1065,15 @@ export default async function CoursesPage({
|
|
|
1051
1065
|
}
|
|
1052
1066
|
```
|
|
1053
1067
|
|
|
1068
|
+
- **Tenant switches.** `enabled` takes `{ category, instructor, price }`; a
|
|
1069
|
+
key that is missing counts as on, so leaving out `enabled` shows every filter
|
|
1070
|
+
(the behaviour before REB-1234). A tenant that never set the switches gets
|
|
1071
|
+
all three `true` from `client.academy.config()`. With every filter off the
|
|
1072
|
+
component renders nothing, and the search box (yours) stays.
|
|
1073
|
+
- **Category needs data and an href.** The category group shows only with
|
|
1074
|
+
`categories` and `hrefs.category`; without them the component behaves as
|
|
1075
|
+
before. An active category slug that is no longer listed keeps the group
|
|
1076
|
+
visible, so it can be cleared.
|
|
1054
1077
|
- **Price is integer cents.** The default bands (`DEFAULT_COURSE_PRICE_BANDS`)
|
|
1055
1078
|
are EUR: up to 50, 50 to 150, 150 to 300, from 300. Pass `priceBands` for
|
|
1056
1079
|
another catalogue and `currencyCode` / `locale` for the labels.
|
|
@@ -1105,6 +1128,33 @@ export default async function Page({ params }) {
|
|
|
1105
1128
|
`lesson-preview-badge`, `lesson-preview-duration`, `lesson-preview-player`,
|
|
1106
1129
|
`lesson-preview-content`.
|
|
1107
1130
|
|
|
1131
|
+
## Course purchase terms — `CoursePurchaseTerms` (REB-1199)
|
|
1132
|
+
|
|
1133
|
+
What a buyer must see before paying for a course, from `client.academy.bySlug()`:
|
|
1134
|
+
|
|
1135
|
+
- **Withdrawal waiver** (`withdrawalWaiverRequired`): checkout asks for a separate box in which the buyer requests immediate access and waives the 14-day withdrawal right.
|
|
1136
|
+
- **Access duration** (`accessDurationMonths`): months of access after enrolment. `null` means no end date, and nothing is shown.
|
|
1137
|
+
- **Refund guarantee** (`refundGuarantee`): the course's terms. `null` means none, and nothing is shown.
|
|
1138
|
+
|
|
1139
|
+
Each term renders only when the course carries it. A course with none renders nothing, not even the heading. It is a Server Component, RSC-safe. The copy is Spanish and neutral; replace any text with `labels`.
|
|
1140
|
+
|
|
1141
|
+
```tsx
|
|
1142
|
+
import { CoursePurchaseTerms } from '@reblu/site-blocks'
|
|
1143
|
+
|
|
1144
|
+
const course = await client.academy.bySlug(slug)
|
|
1145
|
+
|
|
1146
|
+
<CoursePurchaseTerms course={course} heading='Antes de comprar' />
|
|
1147
|
+
|
|
1148
|
+
// In another language:
|
|
1149
|
+
<CoursePurchaseTerms
|
|
1150
|
+
course={course}
|
|
1151
|
+
labels={{
|
|
1152
|
+
withdrawalWaiver: 'Immediate access: you waive the 14-day withdrawal right.',
|
|
1153
|
+
accessDuration: (months) => `Access for ${months} months.`,
|
|
1154
|
+
}}
|
|
1155
|
+
/>
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1108
1158
|
## Page blocks
|
|
1109
1159
|
|
|
1110
1160
|
`PageBlocks` renders a page's registry blocks (`PageDetail.blocks` from
|