summit-registration-lite 7.0.0 → 7.0.1
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.
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# i18n / Translation Pattern
|
|
2
|
+
|
|
3
|
+
## When to Apply
|
|
4
|
+
|
|
5
|
+
Adding user-facing text to components or modifying existing strings.
|
|
6
|
+
|
|
7
|
+
## Pattern
|
|
8
|
+
|
|
9
|
+
**Library:** `i18n-react` — imported as `T`.
|
|
10
|
+
|
|
11
|
+
**Setup (in `registration-lite.js`):**
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import T from 'i18n-react';
|
|
15
|
+
|
|
16
|
+
// Loaded once at component init, falls back to English
|
|
17
|
+
try {
|
|
18
|
+
T.setTexts(require(`../i18n/${language}.json`));
|
|
19
|
+
} catch {
|
|
20
|
+
T.setTexts(require(`../i18n/en.json`));
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Usage in components:**
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import T from 'i18n-react';
|
|
28
|
+
|
|
29
|
+
// Simple key
|
|
30
|
+
T.translate("bar_button.next") // → "Next"
|
|
31
|
+
|
|
32
|
+
// With interpolation
|
|
33
|
+
T.translate("purchase_complete_step.footer_assistance_text", { supportEmail: "help@example.com" })
|
|
34
|
+
// Template: "For further assistance, please email <a href=\"mailto:{supportEmail}\">{supportEmail}</a>"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Translation File Structure
|
|
38
|
+
|
|
39
|
+
`src/i18n/en.json` — flat namespaced by UI section:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"purchase_complete_step": { "title": "...", "initial_order_complete_button": "..." },
|
|
44
|
+
"ticket_type": { "ticket_quantity_tooltip": "..." },
|
|
45
|
+
"promo_code": { "promo_code_tooltip": "..." },
|
|
46
|
+
"bar_button": { "back": "Back", "next": "Next", "get_ticket": "Get Ticket", "pay_now": "Pay Now", "loading": "Loading" }
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Key Points
|
|
51
|
+
|
|
52
|
+
- Namespace keys by component/step: `"section_name.key_name"`
|
|
53
|
+
- Interpolation uses `{variableName}` syntax (not `${}` or `%s`)
|
|
54
|
+
- HTML is allowed in translation values (rendered as-is)
|
|
55
|
+
- Only English (`en.json`) exists — add new languages as `{lang}.json` in `src/i18n/`
|
|
56
|
+
- Components using text must `import T from 'i18n-react'`
|
|
57
|
+
|
|
58
|
+
## Common Mistakes
|
|
59
|
+
|
|
60
|
+
- Hardcoding user-facing strings instead of using `T.translate()`
|
|
61
|
+
- Adding keys without updating `en.json` (renders the key path as literal text)
|
|
62
|
+
- Using wrong namespace (check `en.json` for existing sections before creating new ones)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Multi-Step Registration Flow
|
|
2
|
+
|
|
3
|
+
## When to Apply
|
|
4
|
+
|
|
5
|
+
Adding step-specific logic, modifying step transitions, or rendering step-dependent UI.
|
|
6
|
+
|
|
7
|
+
## Step Constants
|
|
8
|
+
|
|
9
|
+
Defined in `src/utils/constants.js`:
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
export const STEP_SELECT_TICKET_TYPE = 0; // Ticket selection + promo code
|
|
13
|
+
export const STEP_PERSONAL_INFO = 1; // Attendee details + ticket assignment
|
|
14
|
+
export const STEP_PAYMENT = 2; // Payment form (Stripe/LawPay)
|
|
15
|
+
export const STEP_COMPLETE = 3; // Order confirmation
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Step Transitions
|
|
19
|
+
|
|
20
|
+
**Forward flow (happy path):**
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
STEP_SELECT_TICKET_TYPE → (Next/validate promo) → STEP_PERSONAL_INFO
|
|
24
|
+
STEP_PERSONAL_INFO → (submit form) → reserveTicket → STEP_PAYMENT
|
|
25
|
+
STEP_PAYMENT → (pay) → payTicketWithProvider → STEP_COMPLETE
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Special cases:**
|
|
29
|
+
|
|
30
|
+
| Scenario | Transition |
|
|
31
|
+
|----------|------------|
|
|
32
|
+
| Free ticket (cost === 0) | `STEP_PERSONAL_INFO` → skip payment → `STEP_COMPLETE` |
|
|
33
|
+
| Pre-paid ticket | `STEP_PERSONAL_INFO` → skip payment → `STEP_COMPLETE` |
|
|
34
|
+
| Payment failure | `STEP_PAYMENT` → `removeReservedTicket()` → `STEP_PERSONAL_INFO` |
|
|
35
|
+
| No ticket selected + back | Any step → `STEP_SELECT_TICKET_TYPE` |
|
|
36
|
+
|
|
37
|
+
**Back navigation:**
|
|
38
|
+
|
|
39
|
+
- From `STEP_PERSONAL_INFO`: `changeStep(step - 1)`
|
|
40
|
+
- From `STEP_PAYMENT`: `removeReservedTicket()` (clears reservation, reducer resets to `STEP_PERSONAL_INFO`)
|
|
41
|
+
|
|
42
|
+
## Redux Integration
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Action
|
|
46
|
+
export const changeStep = (step) => (dispatch, getState) => {
|
|
47
|
+
dispatch(createAction(CHANGE_STEP)(step));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Reducer
|
|
51
|
+
case CHANGE_STEP: {
|
|
52
|
+
return { ...state, step: payload };
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Default state: `step: STEP_SELECT_TICKET_TYPE`
|
|
57
|
+
|
|
58
|
+
## Rendering Pattern
|
|
59
|
+
|
|
60
|
+
In `registration-lite.js`, each step renders conditionally:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
<StepComponent isActive={step === STEP_SELECT_TICKET_TYPE} ... />
|
|
64
|
+
<StepComponent isActive={step === STEP_PERSONAL_INFO} ... />
|
|
65
|
+
<StepComponent isActive={step === STEP_PAYMENT} ... />
|
|
66
|
+
{step === STEP_COMPLETE && <PurchaseCompleteComponent ... />}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- Steps 0-2 share layout with `ButtonBarComponent`
|
|
70
|
+
- Step 3 (complete) has its own layout, no button bar
|
|
71
|
+
- Button bar renders step-specific buttons based on current `step` value
|
|
72
|
+
|
|
73
|
+
## Common Mistakes
|
|
74
|
+
|
|
75
|
+
- Skipping `removeReservedTicket()` when going back from payment (leaves stale reservation)
|
|
76
|
+
- Not checking `reservation` existence before allowing forward navigation
|
|
77
|
+
- Adding steps without updating `ButtonBarComponent` (buttons won't render for new step)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Utility Functions
|
|
2
|
+
|
|
3
|
+
## When to Apply
|
|
4
|
+
|
|
5
|
+
Working with ticket pricing, order status checks, payment provider resolution, or UI color logic.
|
|
6
|
+
|
|
7
|
+
## Key Functions (`src/utils/utils.js`)
|
|
8
|
+
|
|
9
|
+
### Order/Ticket Status Checks
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
isFreeOrder(reservation) // reservation.amount === 0
|
|
13
|
+
isPrePaidOrder(reservation) // status === 'Paid' && payment_method === 'Offline'
|
|
14
|
+
isPrePaidTicketType(ticketType) // ticketType.sub_type === 'PrePaid'
|
|
15
|
+
hasDiscountApplied(ticketType) // has cost_with_applied_discount !== cost
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Used in payment providers to decide whether to skip the payment gateway.
|
|
19
|
+
|
|
20
|
+
### Pricing Display
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
getTicketCost(ticket, quantity) // Returns JSX: strikethrough original + discounted price, or just price
|
|
24
|
+
getTicketTaxes(ticket, taxes) // Returns tax label string: " plus Tax A & Tax B"
|
|
25
|
+
formatCurrency(amount, { currency }) // From helpers/ — locale-aware currency formatting
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Payment Provider Resolution
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
getCurrentProvider(summit)
|
|
32
|
+
// Iterates summit.payment_profiles for application_type === 'Registration'
|
|
33
|
+
// Returns { publicKey, provider } — uses test vs live key based on test_mode_enabled
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### UI Helpers
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
getContrastingTextColor(bgColor, lightColor, darkColor) // WCAG luminance contrast
|
|
40
|
+
parseColor(input, element) // Resolves CSS variables to RGB
|
|
41
|
+
removeWhiteSpaces(value) // Strip all whitespace
|
|
42
|
+
isEmptyString(val) // Trim-aware empty check
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Error Tracking
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
handleSentryException(err) // Sends to Sentry if window.SENTRY_DSN is set, else console.log
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Analytics
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
buildTrackEvent(data, ticketQuantity, promoCode)
|
|
55
|
+
// Builds GA4-style event data with currency, items_array, discount
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Helper Exports (`src/helpers/`)
|
|
59
|
+
|
|
60
|
+
Barrel export from `src/helpers/index.js`:
|
|
61
|
+
|
|
62
|
+
- `capitalizeFirstLetter` — text formatting
|
|
63
|
+
- `formatCurrency` — locale-aware currency display
|
|
64
|
+
- `formatErrorMessage` — error message normalization
|
|
65
|
+
- `getTicketMaxQuantity` — ticket quantity constraints
|
|
66
|
+
|
|
67
|
+
## Common Mistakes
|
|
68
|
+
|
|
69
|
+
- Using `reservation.amount === 0` directly instead of `isFreeOrder()` (misses edge cases)
|
|
70
|
+
- Forgetting `isPrePaidOrder()` check alongside `isFreeOrder()` in payment flows
|
|
71
|
+
- Not handling `getCurrentProvider()` returning `{ publicKey: null, provider: '' }` when no payment profile exists
|