igloo-d2c-components 1.0.12 → 1.0.14
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/README.md +1153 -341
- package/dist/cjs/index.js +256 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +256 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/types/components/BenefitsSummary/BenefitsSummary.d.ts +22 -0
- package/dist/types/components/BenefitsSummary/index.d.ts +2 -0
- package/dist/types/components/BenefitsSummary/styled.d.ts +29 -0
- package/dist/types/components/BenefitsSummary/types.d.ts +58 -0
- package/dist/types/components/FAQAccordion/FAQAccordion.d.ts +22 -0
- package/dist/types/components/FAQAccordion/index.d.ts +2 -0
- package/dist/types/components/FAQAccordion/styled.d.ts +37 -0
- package/dist/types/components/FAQAccordion/types.d.ts +57 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/storybook-components/BenefitsSummary.stories.d.ts +37 -0
- package/dist/types/storybook-components/FAQAccordion.stories.d.ts +37 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,17 +5,31 @@ Reusable React component library with **centralized tenant themes** and tenant-a
|
|
|
5
5
|
## 📋 Table of Contents
|
|
6
6
|
|
|
7
7
|
- [Overview](#-overview)
|
|
8
|
+
- [Project Architecture](#-project-architecture)
|
|
8
9
|
- [Features](#-features)
|
|
9
10
|
- [Installation](#-installation)
|
|
10
11
|
- [Quick Start](#-quick-start)
|
|
11
12
|
- [Centralized Themes](#-centralized-themes)
|
|
12
13
|
- [Components](#-components)
|
|
14
|
+
- [General Components](#general-components)
|
|
15
|
+
- [Interactive Components](#interactive-components)
|
|
16
|
+
- [Checkout Components](#checkout-components)
|
|
17
|
+
- [Form Components](#form-components)
|
|
13
18
|
- [Hooks & Utilities](#-hooks--utilities)
|
|
19
|
+
- [Asset Management](#-asset-management)
|
|
20
|
+
- [Integration Guide](#-integration-guide)
|
|
21
|
+
- [Multi-Tenant Architecture](#multi-tenant-architecture)
|
|
22
|
+
- [Checkout Flow Integration](#checkout-flow-integration)
|
|
23
|
+
- [Recommendations Feature](#recommendations-feature)
|
|
24
|
+
- [Header Integration](#header-integration)
|
|
25
|
+
- [Routing Guide](#routing-guide)
|
|
14
26
|
- [Development](#-development)
|
|
15
|
-
- [Publishing](#-publishing)
|
|
16
27
|
- [Storybook](#-storybook)
|
|
28
|
+
- [Build Pipeline](#-build-pipeline)
|
|
29
|
+
- [Publishing](#-publishing)
|
|
17
30
|
- [Technical Details](#-technical-details)
|
|
18
31
|
- [Troubleshooting](#-troubleshooting)
|
|
32
|
+
- [Changelog](#-changelog)
|
|
19
33
|
- [Contributing](#-contributing)
|
|
20
34
|
|
|
21
35
|
---
|
|
@@ -24,6 +38,15 @@ Reusable React component library with **centralized tenant themes** and tenant-a
|
|
|
24
38
|
|
|
25
39
|
The D2C Component Library provides reusable, tenant-aware UI components with **centralized theme management**. All tenant themes are defined in one place, ensuring consistency across all applications.
|
|
26
40
|
|
|
41
|
+
### What Are These Projects?
|
|
42
|
+
|
|
43
|
+
We've built a **multi-tenant B2C insurance platform** that enables rapid deployment of white-label insurance applications for different partners.
|
|
44
|
+
|
|
45
|
+
| Project | Purpose |
|
|
46
|
+
| ------------------------- | --------------------------------------------------------------------------- |
|
|
47
|
+
| **d2c-component-library** | Shared component library with centralized themes and reusable UI components |
|
|
48
|
+
| **b2c-web-demo** | Multi-tenant web application consuming the component library |
|
|
49
|
+
|
|
27
50
|
### Key Highlights
|
|
28
51
|
|
|
29
52
|
- 🎨 **Centralized Themes** - All tenant themes (Igloo, CIMB, AmmetLife) in one library
|
|
@@ -33,6 +56,70 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
|
|
|
33
56
|
- 📖 **Full TypeScript Support** - Complete type definitions
|
|
34
57
|
- ⚡ **Tree-Shakeable** - Import only what you need
|
|
35
58
|
|
|
59
|
+
### Supported Tenants
|
|
60
|
+
|
|
61
|
+
| Tenant | Port | Description |
|
|
62
|
+
| ------------- | ---- | ----------------------- |
|
|
63
|
+
| **Igloo** | 8000 | Default insurance brand |
|
|
64
|
+
| **AmmetLife** | 8001 | Life insurance partner |
|
|
65
|
+
| **CIMB** | 8002 | Banking partner |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 🏗️ Project Architecture
|
|
70
|
+
|
|
71
|
+
### The Solution Architecture
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
75
|
+
│ d2c-component-library │
|
|
76
|
+
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
77
|
+
│ │ Centralized Themes ││
|
|
78
|
+
│ │ ┌───────────────────────┐ ┌───────────────────────┐ ││
|
|
79
|
+
│ │ │ iglooTheme │ │ ammetlifeTheme │ ││
|
|
80
|
+
│ │ └───────────────────────┘ └───────────────────────┘ ││
|
|
81
|
+
│ └─────────────────────────────────────────────────────────────┘│
|
|
82
|
+
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
83
|
+
│ │ Shared Components ││
|
|
84
|
+
│ │ Button │ Card │ Banner │ Header │ CheckoutProgress │ ... ││
|
|
85
|
+
│ └─────────────────────────────────────────────────────────────┘│
|
|
86
|
+
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
87
|
+
│ │ Theme Utilities ││
|
|
88
|
+
│ │ TenantThemeProvider │ useTenantTheme │ getTenantTheme ││
|
|
89
|
+
│ └─────────────────────────────────────────────────────────────┘│
|
|
90
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
91
|
+
│
|
|
92
|
+
▼
|
|
93
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
94
|
+
│ b2c-web-demo │
|
|
95
|
+
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
96
|
+
│ │ Tenant Configurations ││
|
|
97
|
+
│ │ ┌───────────────────────┐ ┌───────────────────────┐ ││
|
|
98
|
+
│ │ │ igloo.ts │ │ ammetlife.ts │ ││
|
|
99
|
+
│ │ │ (uses iglooTheme) │ │ (uses ammetlifeTheme) │ ││
|
|
100
|
+
│ │ └───────────────────────┘ └───────────────────────┘ ││
|
|
101
|
+
│ └─────────────────────────────────────────────────────────────┘│
|
|
102
|
+
│ ┌─────────────────────────────────────────────────────────────┐│
|
|
103
|
+
│ │ Single Codebase, Multiple Tenants ││
|
|
104
|
+
│ │ yarn start-igloo → http://localhost:8000 ││
|
|
105
|
+
│ │ yarn start-ammetlife → http://localhost:8001 ││
|
|
106
|
+
│ └─────────────────────────────────────────────────────────────┘│
|
|
107
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Technical Stack
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Frontend Framework: React 17 + TypeScript
|
|
114
|
+
Build System: UmiJS (React framework) for b2c-web-demo
|
|
115
|
+
UI Components: MUI v5 + Custom Components
|
|
116
|
+
Styling: Emotion (CSS-in-JS) + Tailwind CSS
|
|
117
|
+
State Management: Recoil + React Context
|
|
118
|
+
Component Library: Rollup (ES2015 output)
|
|
119
|
+
Documentation: Storybook
|
|
120
|
+
Package Manager: Yarn
|
|
121
|
+
```
|
|
122
|
+
|
|
36
123
|
---
|
|
37
124
|
|
|
38
125
|
## ✨ Features
|
|
@@ -47,41 +134,28 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
|
|
|
47
134
|
|
|
48
135
|
### Available Themes
|
|
49
136
|
|
|
50
|
-
| Tenant
|
|
51
|
-
|
|
52
|
-
| **Igloo**
|
|
53
|
-
| **CIMB**
|
|
54
|
-
| **AmmetLife** | `ammetlifeTheme` | Life insurance partner
|
|
55
|
-
|
|
56
|
-
###
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- **Footer** - Application footer with links
|
|
65
|
-
|
|
66
|
-
#### Interactive Components
|
|
67
|
-
- **RecommendationsDrawer** - Mobile drawer for user recommendations
|
|
68
|
-
- **ProductSelectionDrawer** - Mobile drawer for product selection
|
|
69
|
-
- **QuestionSection** - Interactive question component
|
|
70
|
-
- **OptionButton** - Customizable option button
|
|
71
|
-
- **ToggleGroup** - Toggle button group
|
|
72
|
-
|
|
73
|
-
#### Checkout Components
|
|
74
|
-
- **CheckoutProgress** - Progress bar with step indicator
|
|
75
|
-
- **ProductCard** - Product information card for checkout
|
|
76
|
-
- **CheckoutHeader** - Complete checkout header (progress + product + section)
|
|
77
|
-
- **CheckoutFormButton** - Fixed/floating form button
|
|
78
|
-
- **HealthQuestionGroup** - Health question with Yes/No options
|
|
137
|
+
| Tenant | Theme Export | Description |
|
|
138
|
+
| ------------- | ---------------- | ----------------------- |
|
|
139
|
+
| **Igloo** | `iglooTheme` | Default insurance brand |
|
|
140
|
+
| **CIMB** | `cimbTheme` | Banking partner theme |
|
|
141
|
+
| **AmmetLife** | `ammetlifeTheme` | Life insurance partner |
|
|
142
|
+
|
|
143
|
+
### Component Categories
|
|
144
|
+
|
|
145
|
+
| Category | Components |
|
|
146
|
+
| --------------- | ----------------------------------------------------------------------------------------- |
|
|
147
|
+
| **General** | Button, Card, Banner, Header, NewHeader, Footer |
|
|
148
|
+
| **Interactive** | RecommendationsDrawer, ProductSelectionDrawer, QuestionSection, OptionButton, ToggleGroup |
|
|
149
|
+
| **Checkout** | CheckoutProgress, ProductCard, CheckoutHeader, CheckoutFormButton, HealthQuestionGroup |
|
|
150
|
+
| **Forms** | PersonalInformationForm, ContactDetailsForm, HealthInformationForm |
|
|
79
151
|
|
|
80
152
|
### Hooks
|
|
81
153
|
|
|
82
154
|
- `useTenantTheme()` - Access tenant theme and ID
|
|
83
155
|
- `useTenantId()` - Get current tenant ID
|
|
84
156
|
- `useIsTenant()` - Check tenant match
|
|
157
|
+
- `useTenantLogo()` - Get tenant logo
|
|
158
|
+
- `useTenantAsset()` - Get tenant-specific asset
|
|
85
159
|
|
|
86
160
|
### Utilities
|
|
87
161
|
|
|
@@ -90,6 +164,27 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
|
|
|
90
164
|
- `getThemeColor()` - Extract colors from theme
|
|
91
165
|
- `createThemeCSSVariables()` - Generate CSS variables
|
|
92
166
|
|
|
167
|
+
### Key Benefits
|
|
168
|
+
|
|
169
|
+
#### For Development Teams
|
|
170
|
+
|
|
171
|
+
| Benefit | Impact |
|
|
172
|
+
| -------------------------- | -------------------------------------------------------- |
|
|
173
|
+
| **Single Source of Truth** | Update themes once, reflected everywhere |
|
|
174
|
+
| **~585 Lines Removed** | From consuming apps (no more duplicated themes) |
|
|
175
|
+
| **Type Safety** | Full TypeScript support with interfaces |
|
|
176
|
+
| **Faster Development** | Reuse tested components instead of building from scratch |
|
|
177
|
+
| **Better DX** | Hot reload, Storybook for component development |
|
|
178
|
+
|
|
179
|
+
#### For Business
|
|
180
|
+
|
|
181
|
+
| Benefit | Impact |
|
|
182
|
+
| ----------------------------- | -------------------------------------------- |
|
|
183
|
+
| **Faster Partner Onboarding** | Days instead of weeks to launch a new tenant |
|
|
184
|
+
| **Consistent UX** | Same quality experience across all brands |
|
|
185
|
+
| **Reduced Costs** | One team maintains one codebase |
|
|
186
|
+
| **Scalability** | Easy to add new tenants and features |
|
|
187
|
+
|
|
93
188
|
---
|
|
94
189
|
|
|
95
190
|
## 📦 Installation
|
|
@@ -119,6 +214,7 @@ yarn install
|
|
|
119
214
|
```
|
|
120
215
|
|
|
121
216
|
**Workflow:**
|
|
217
|
+
|
|
122
218
|
```bash
|
|
123
219
|
# Make changes to library
|
|
124
220
|
cd d2c-component-library
|
|
@@ -135,6 +231,7 @@ yarn install # Copies updated build
|
|
|
135
231
|
For production deployments and CI/CD.
|
|
136
232
|
|
|
137
233
|
**Install:**
|
|
234
|
+
|
|
138
235
|
```bash
|
|
139
236
|
yarn add igloo-d2c-components
|
|
140
237
|
# or
|
|
@@ -142,6 +239,7 @@ npm install igloo-d2c-components
|
|
|
142
239
|
```
|
|
143
240
|
|
|
144
241
|
**Configure authentication (if using private registry):**
|
|
242
|
+
|
|
145
243
|
```bash
|
|
146
244
|
# For npm
|
|
147
245
|
export NPM_AUTH_TOKEN="your-npm-token"
|
|
@@ -150,6 +248,28 @@ export NPM_AUTH_TOKEN="your-npm-token"
|
|
|
150
248
|
export GITLAB_NPM_TOKEN="glpat-your-token"
|
|
151
249
|
```
|
|
152
250
|
|
|
251
|
+
### Component Library Management Scripts (in b2c-web-demo)
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Check installed version
|
|
255
|
+
yarn lib:check
|
|
256
|
+
|
|
257
|
+
# Get package information
|
|
258
|
+
yarn lib:info
|
|
259
|
+
|
|
260
|
+
# Upgrade to latest version (from registry)
|
|
261
|
+
yarn lib:upgrade
|
|
262
|
+
|
|
263
|
+
# Install local development version
|
|
264
|
+
yarn lib:install-local
|
|
265
|
+
|
|
266
|
+
# Install registry version
|
|
267
|
+
yarn lib:install-registry
|
|
268
|
+
|
|
269
|
+
# Verify registry configuration
|
|
270
|
+
yarn lib:verify-registry
|
|
271
|
+
```
|
|
272
|
+
|
|
153
273
|
---
|
|
154
274
|
|
|
155
275
|
## 🚀 Quick Start
|
|
@@ -227,6 +347,7 @@ function MyPage() {
|
|
|
227
347
|
### Why Centralized Themes?
|
|
228
348
|
|
|
229
349
|
**Before** (❌ Old Way):
|
|
350
|
+
|
|
230
351
|
```typescript
|
|
231
352
|
// In each consuming app - duplicated code
|
|
232
353
|
const iglooTheme = {
|
|
@@ -238,6 +359,7 @@ const iglooTheme = {
|
|
|
238
359
|
```
|
|
239
360
|
|
|
240
361
|
**After** (✅ New Way):
|
|
362
|
+
|
|
241
363
|
```typescript
|
|
242
364
|
// Import from library - single source of truth
|
|
243
365
|
import { iglooTheme } from 'igloo-d2c-components'
|
|
@@ -290,13 +412,18 @@ interface TenantThemeConfig {
|
|
|
290
412
|
fontFamily: string
|
|
291
413
|
}
|
|
292
414
|
logo: string
|
|
415
|
+
logoDark?: string
|
|
416
|
+
logoAlt?: string
|
|
417
|
+
logoWhite?: string
|
|
293
418
|
favicon: string
|
|
419
|
+
assetBaseUrl?: string
|
|
294
420
|
}
|
|
295
421
|
```
|
|
296
422
|
|
|
297
423
|
### Using Themes
|
|
298
424
|
|
|
299
425
|
**In Tenant Configuration:**
|
|
426
|
+
|
|
300
427
|
```typescript
|
|
301
428
|
// config/tenants/igloo.ts
|
|
302
429
|
import { iglooTheme } from 'igloo-d2c-components'
|
|
@@ -308,19 +435,8 @@ const iglooConfig: TenantConfig = {
|
|
|
308
435
|
}
|
|
309
436
|
```
|
|
310
437
|
|
|
311
|
-
**Dynamic Loading:**
|
|
312
|
-
```typescript
|
|
313
|
-
import { getTenantTheme, isValidTenantId } from 'igloo-d2c-components'
|
|
314
|
-
|
|
315
|
-
function loadTheme(tenantId: string) {
|
|
316
|
-
if (isValidTenantId(tenantId)) {
|
|
317
|
-
return getTenantTheme(tenantId)
|
|
318
|
-
}
|
|
319
|
-
throw new Error(`Invalid tenant: ${tenantId}`)
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
438
|
**In Components:**
|
|
439
|
+
|
|
324
440
|
```typescript
|
|
325
441
|
import { useTenantTheme } from 'igloo-d2c-components'
|
|
326
442
|
|
|
@@ -338,19 +454,13 @@ function MyComponent() {
|
|
|
338
454
|
}
|
|
339
455
|
```
|
|
340
456
|
|
|
341
|
-
### Theme Benefits
|
|
342
|
-
|
|
343
|
-
- ✅ **Single source of truth** - Update in one place
|
|
344
|
-
- ✅ **Type-safe** - Full TypeScript support
|
|
345
|
-
- ✅ **Consistent** - Same themes across all apps
|
|
346
|
-
- ✅ **Maintainable** - Easy to update and extend
|
|
347
|
-
- ✅ **Scalable** - Add new tenants easily
|
|
348
|
-
|
|
349
457
|
---
|
|
350
458
|
|
|
351
459
|
## 📚 Components
|
|
352
460
|
|
|
353
|
-
###
|
|
461
|
+
### General Components
|
|
462
|
+
|
|
463
|
+
#### Button
|
|
354
464
|
|
|
355
465
|
Tenant-aware button component based on MUI Button.
|
|
356
466
|
|
|
@@ -369,11 +479,12 @@ import { Button } from 'igloo-d2c-components'
|
|
|
369
479
|
```
|
|
370
480
|
|
|
371
481
|
**Props:**
|
|
482
|
+
|
|
372
483
|
- `tenantColored?: boolean` - Use tenant primary color
|
|
373
484
|
- `variant?: 'text' | 'outlined' | 'contained'` - Button variant
|
|
374
485
|
- All MUI ButtonProps
|
|
375
486
|
|
|
376
|
-
|
|
487
|
+
#### Card
|
|
377
488
|
|
|
378
489
|
Tenant-aware card component based on MUI Card.
|
|
379
490
|
|
|
@@ -389,14 +500,14 @@ import { Card } from 'igloo-d2c-components'
|
|
|
389
500
|
```
|
|
390
501
|
|
|
391
502
|
**Props:**
|
|
503
|
+
|
|
392
504
|
- `title?: React.ReactNode` - Card title
|
|
393
505
|
- `content?: React.ReactNode` - Card content
|
|
394
506
|
- `actions?: React.ReactNode` - Card actions
|
|
395
507
|
- `tenantAccent?: boolean` - Add tenant-colored top border
|
|
396
|
-
- `headerAction?: React.ReactNode` - Action in header
|
|
397
508
|
- All MUI CardProps
|
|
398
509
|
|
|
399
|
-
|
|
510
|
+
#### Banner
|
|
400
511
|
|
|
401
512
|
Promotional banner with tenant theming.
|
|
402
513
|
|
|
@@ -411,12 +522,402 @@ import { Banner } from 'igloo-d2c-components'
|
|
|
411
522
|
/>
|
|
412
523
|
```
|
|
413
524
|
|
|
525
|
+
#### NewHeader
|
|
526
|
+
|
|
527
|
+
Simplified header component with mobile drawer navigation.
|
|
528
|
+
|
|
529
|
+
```tsx
|
|
530
|
+
import { NewHeader } from 'igloo-d2c-components'
|
|
531
|
+
|
|
532
|
+
<NewHeader
|
|
533
|
+
logo="/path/to/logo.svg"
|
|
534
|
+
navigationLinks={[
|
|
535
|
+
{
|
|
536
|
+
key: 'car',
|
|
537
|
+
label: 'Car Insurance',
|
|
538
|
+
onClick: () => navigate('/car')
|
|
539
|
+
}
|
|
540
|
+
]}
|
|
541
|
+
additionalMenuSections={[
|
|
542
|
+
{
|
|
543
|
+
title: 'Account',
|
|
544
|
+
items: [
|
|
545
|
+
{ key: 'login', label: 'Log in', onClick: handleLogin }
|
|
546
|
+
]
|
|
547
|
+
}
|
|
548
|
+
]}
|
|
549
|
+
onLogoClick={() => navigate('/')}
|
|
550
|
+
/>
|
|
551
|
+
```
|
|
552
|
+
|
|
414
553
|
**Props:**
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
interface NewHeaderProps {
|
|
557
|
+
logo: string // Logo image source
|
|
558
|
+
navigationLinks?: NewHeaderNavigationLink[]
|
|
559
|
+
additionalMenuSections?: {
|
|
560
|
+
title?: string
|
|
561
|
+
items: NewHeaderNavigationLink[]
|
|
562
|
+
}[]
|
|
563
|
+
isMobile?: boolean
|
|
564
|
+
onLogoClick?: () => void
|
|
565
|
+
onMenuOpen?: () => void
|
|
566
|
+
onMenuClose?: () => void
|
|
567
|
+
customDrawerContent?: React.ReactNode
|
|
568
|
+
formatMessage?: (descriptor: { id: string }) => string
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Interactive Components
|
|
573
|
+
|
|
574
|
+
#### RecommendationsDrawer
|
|
575
|
+
|
|
576
|
+
Mobile drawer for collecting user preferences and showing personalized recommendations.
|
|
577
|
+
|
|
578
|
+
```tsx
|
|
579
|
+
import {
|
|
580
|
+
RecommendationsDrawer,
|
|
581
|
+
QuestionSection,
|
|
582
|
+
OptionButton,
|
|
583
|
+
ToggleGroup
|
|
584
|
+
} from 'igloo-d2c-components'
|
|
585
|
+
|
|
586
|
+
function MyComponent() {
|
|
587
|
+
const [open, setOpen] = React.useState(false)
|
|
588
|
+
const [selectedOption, setSelectedOption] = React.useState('')
|
|
589
|
+
|
|
590
|
+
const options = [
|
|
591
|
+
{ value: 'option1', label: 'Option 1', icon: '🎯' },
|
|
592
|
+
{ value: 'option2', label: 'Option 2', icon: '✨' },
|
|
593
|
+
]
|
|
594
|
+
|
|
595
|
+
return (
|
|
596
|
+
<>
|
|
597
|
+
<Button onClick={() => setOpen(true)}>
|
|
598
|
+
See my recommendations
|
|
599
|
+
</Button>
|
|
600
|
+
|
|
601
|
+
<RecommendationsDrawer
|
|
602
|
+
open={open}
|
|
603
|
+
onClose={() => setOpen(false)}
|
|
604
|
+
title="Personalize Your Plan"
|
|
605
|
+
subtitle="Answer a few questions"
|
|
606
|
+
primaryButtonText="Next"
|
|
607
|
+
onPrimaryAction={handleSubmit}
|
|
608
|
+
>
|
|
609
|
+
<QuestionSection
|
|
610
|
+
question="What's your preference?"
|
|
611
|
+
options={options}
|
|
612
|
+
selectedValue={selectedOption}
|
|
613
|
+
onSelect={setSelectedOption}
|
|
614
|
+
renderOption={(option, isSelected) => (
|
|
615
|
+
<OptionButton
|
|
616
|
+
key={option.value}
|
|
617
|
+
value={option.value}
|
|
618
|
+
label={option.label}
|
|
619
|
+
icon={option.icon}
|
|
620
|
+
selected={isSelected}
|
|
621
|
+
onClick={setSelectedOption}
|
|
622
|
+
/>
|
|
623
|
+
)}
|
|
624
|
+
/>
|
|
625
|
+
</RecommendationsDrawer>
|
|
626
|
+
</>
|
|
627
|
+
)
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**RecommendationsDrawer Props:**
|
|
632
|
+
|
|
633
|
+
```typescript
|
|
634
|
+
interface RecommendationsDrawerProps {
|
|
635
|
+
open: boolean
|
|
636
|
+
onClose: () => void
|
|
637
|
+
children: React.ReactNode
|
|
638
|
+
headerIcon?: string
|
|
639
|
+
title?: string
|
|
640
|
+
subtitle?: string
|
|
641
|
+
showBackButton?: boolean
|
|
642
|
+
onBack?: () => void
|
|
643
|
+
primaryButtonText?: string
|
|
644
|
+
onPrimaryAction?: () => void
|
|
645
|
+
primaryButtonDisabled?: boolean
|
|
646
|
+
secondaryButtonText?: string
|
|
647
|
+
onSecondaryAction?: () => void
|
|
648
|
+
showFooter?: boolean
|
|
649
|
+
customFooter?: React.ReactNode
|
|
650
|
+
formatMessage?: (descriptor: { id: string }) => string
|
|
651
|
+
}
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
#### ProductSelectionDrawer
|
|
655
|
+
|
|
656
|
+
Mobile-first bottom drawer for displaying insurance products in a grid.
|
|
657
|
+
|
|
658
|
+
```tsx
|
|
659
|
+
import { ProductSelectionDrawer, Product } from 'igloo-d2c-components'
|
|
660
|
+
|
|
661
|
+
const products: Product[] = [
|
|
662
|
+
{
|
|
663
|
+
id: 'life-byond',
|
|
664
|
+
name: 'LIFE BYOND',
|
|
665
|
+
type: 'Term Plan',
|
|
666
|
+
logo: '/path/to/logo.png',
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
id: 'health-cvr',
|
|
670
|
+
name: 'HEALTH CVR',
|
|
671
|
+
type: 'CI Plan',
|
|
672
|
+
logo: '/path/to/logo.png',
|
|
673
|
+
},
|
|
674
|
+
]
|
|
675
|
+
|
|
676
|
+
<ProductSelectionDrawer
|
|
677
|
+
open={open}
|
|
678
|
+
onClose={() => setOpen(false)}
|
|
679
|
+
products={products}
|
|
680
|
+
onProductSelect={(productId) => {
|
|
681
|
+
console.log('Selected:', productId)
|
|
682
|
+
setOpen(false)
|
|
683
|
+
}}
|
|
684
|
+
title="Select your product"
|
|
685
|
+
subtitle="Pick the product that suits your protection goals"
|
|
686
|
+
viewPlansButtonText="View plans"
|
|
687
|
+
/>
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
#### ToggleGroup
|
|
691
|
+
|
|
692
|
+
Segmented control for binary/multiple choice toggles.
|
|
693
|
+
|
|
694
|
+
```tsx
|
|
695
|
+
import { ToggleGroup } from 'igloo-d2c-components'
|
|
696
|
+
|
|
697
|
+
<ToggleGroup
|
|
698
|
+
options={[
|
|
699
|
+
{ value: 'domestic', label: 'Domestic', icon: '/icon1.svg' },
|
|
700
|
+
{ value: 'international', label: 'International', icon: '/icon2.svg' }
|
|
701
|
+
]}
|
|
702
|
+
value={travelType}
|
|
703
|
+
onChange={setTravelType}
|
|
704
|
+
/>
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### Checkout Components
|
|
708
|
+
|
|
709
|
+
#### CheckoutProgress
|
|
710
|
+
|
|
711
|
+
Progress bar with step indicator for multi-step checkout flows.
|
|
712
|
+
|
|
713
|
+
```tsx
|
|
714
|
+
import { CheckoutProgress } from 'igloo-d2c-components'
|
|
715
|
+
|
|
716
|
+
<CheckoutProgress
|
|
717
|
+
currentStep={0}
|
|
718
|
+
totalSteps={3}
|
|
719
|
+
onBack={() => handleBack()}
|
|
720
|
+
showBackButton={true}
|
|
721
|
+
/>
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**Props:**
|
|
725
|
+
|
|
726
|
+
| Prop | Type | Default | Description |
|
|
727
|
+
| ---------------- | ------------ | -------- | ------------------------------------ |
|
|
728
|
+
| `currentStep` | `number` | Required | Current step (0-indexed) |
|
|
729
|
+
| `totalSteps` | `number` | Required | Total number of steps |
|
|
730
|
+
| `onBack` | `() => void` | - | Callback when back button is clicked |
|
|
731
|
+
| `showBackButton` | `boolean` | `true` | Whether to show the back button |
|
|
732
|
+
|
|
733
|
+
#### ProductCard
|
|
734
|
+
|
|
735
|
+
Product information card for checkout flows.
|
|
736
|
+
|
|
737
|
+
```tsx
|
|
738
|
+
import { ProductCard } from 'igloo-d2c-components'
|
|
739
|
+
|
|
740
|
+
<ProductCard
|
|
741
|
+
productName="LIFE BYOND"
|
|
742
|
+
planName="Plan A"
|
|
743
|
+
price="25"
|
|
744
|
+
currency="RM"
|
|
745
|
+
period="/month"
|
|
746
|
+
logoUrl="path/to/logo.png"
|
|
747
|
+
showIndicator={true}
|
|
748
|
+
/>
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
#### CheckoutHeader
|
|
752
|
+
|
|
753
|
+
Complete header component combining progress, product card, and section information.
|
|
754
|
+
|
|
755
|
+
```tsx
|
|
756
|
+
import { CheckoutHeader } from 'igloo-d2c-components'
|
|
757
|
+
|
|
758
|
+
<CheckoutHeader
|
|
759
|
+
progress={{
|
|
760
|
+
currentStep: 0,
|
|
761
|
+
totalSteps: 3,
|
|
762
|
+
onBack: () => handleBack(),
|
|
763
|
+
}}
|
|
764
|
+
product={{
|
|
765
|
+
productName: 'LIFE BYOND',
|
|
766
|
+
planName: 'Plan A',
|
|
767
|
+
price: '25',
|
|
768
|
+
currency: 'RM',
|
|
769
|
+
period: '/month',
|
|
770
|
+
}}
|
|
771
|
+
sectionTitle="Personal information"
|
|
772
|
+
sectionDescription="Let's get to know you better..."
|
|
773
|
+
sticky={true}
|
|
774
|
+
/>
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
#### CheckoutFormButton
|
|
778
|
+
|
|
779
|
+
Fixed or floating button for form submission.
|
|
780
|
+
|
|
781
|
+
```tsx
|
|
782
|
+
import { CheckoutFormButton } from 'igloo-d2c-components'
|
|
783
|
+
|
|
784
|
+
<CheckoutFormButton
|
|
785
|
+
text="Next"
|
|
786
|
+
disabled={!isValid}
|
|
787
|
+
onClick={handleSubmit}
|
|
788
|
+
fixed={true}
|
|
789
|
+
type="button"
|
|
790
|
+
loading={isSubmitting}
|
|
791
|
+
/>
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
**Tenant Theme Support:** The button automatically uses tenant-specific colors:
|
|
795
|
+
|
|
796
|
+
- **AmmetLife**: Blue (#317ABC)
|
|
797
|
+
- **CIMB**: Red (#D71920)
|
|
798
|
+
- **Igloo**: Black (#13131B)
|
|
799
|
+
|
|
800
|
+
#### HealthQuestionGroup
|
|
801
|
+
|
|
802
|
+
Health questions with Yes/No button options.
|
|
803
|
+
|
|
804
|
+
```tsx
|
|
805
|
+
import { HealthQuestionGroup } from 'igloo-d2c-components'
|
|
806
|
+
|
|
807
|
+
<HealthQuestionGroup
|
|
808
|
+
question="Have you ever had any ongoing or past health conditions?"
|
|
809
|
+
questionNumber={1}
|
|
810
|
+
value={healthConditions}
|
|
811
|
+
onChange={(value) => setHealthConditions(value)}
|
|
812
|
+
error={errors.healthConditions}
|
|
813
|
+
labels={{ yes: 'Yes', no: 'No' }}
|
|
814
|
+
/>
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### Form Components
|
|
818
|
+
|
|
819
|
+
The library includes three reusable checkout form components designed to be **form library agnostic**.
|
|
820
|
+
|
|
821
|
+
#### PersonalInformationForm
|
|
822
|
+
|
|
823
|
+
Collects personal details, occupation, and banking information.
|
|
824
|
+
|
|
825
|
+
```tsx
|
|
826
|
+
import { PersonalInformationForm } from 'igloo-d2c-components'
|
|
827
|
+
|
|
828
|
+
<PersonalInformationForm
|
|
829
|
+
renderField={renderField}
|
|
830
|
+
fields={{
|
|
831
|
+
full_name: {
|
|
832
|
+
name: 'full_name',
|
|
833
|
+
label: 'Full name',
|
|
834
|
+
value: formik.values.full_name,
|
|
835
|
+
error: formik.errors.full_name,
|
|
836
|
+
touched: formik.touched.full_name,
|
|
837
|
+
helperText: 'Full name as per your ID card',
|
|
838
|
+
onChange: formik.handleChange,
|
|
839
|
+
onBlur: formik.handleBlur,
|
|
840
|
+
},
|
|
841
|
+
nric: { /* ... */ },
|
|
842
|
+
date_of_birth: { /* ... */ },
|
|
843
|
+
gender: { /* ... */ },
|
|
844
|
+
// ... other fields
|
|
845
|
+
}}
|
|
846
|
+
consents={{
|
|
847
|
+
bank_account_confirmation: {
|
|
848
|
+
checked: formik.values.bank_account_confirmation,
|
|
849
|
+
onChange: (checked) =>
|
|
850
|
+
formik.setFieldValue('bank_account_confirmation', checked),
|
|
851
|
+
error: formik.errors.bank_account_confirmation,
|
|
852
|
+
},
|
|
853
|
+
marketing_consent: {
|
|
854
|
+
checked: formik.values.marketing_consent,
|
|
855
|
+
onChange: (checked) =>
|
|
856
|
+
formik.setFieldValue('marketing_consent', checked),
|
|
857
|
+
},
|
|
858
|
+
}}
|
|
859
|
+
onSubmit={formik.handleSubmit}
|
|
860
|
+
/>
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
#### ContactDetailsForm
|
|
864
|
+
|
|
865
|
+
Collects contact and address information.
|
|
866
|
+
|
|
867
|
+
```tsx
|
|
868
|
+
import { ContactDetailsForm } from 'igloo-d2c-components'
|
|
869
|
+
|
|
870
|
+
<ContactDetailsForm
|
|
871
|
+
renderField={renderField}
|
|
872
|
+
fields={{
|
|
873
|
+
phone_number: { /* ... */ },
|
|
874
|
+
email_address: { /* ... */ },
|
|
875
|
+
residential_address: { /* ... */ },
|
|
876
|
+
postal_code: { /* ... */ },
|
|
877
|
+
city: { /* ... */ },
|
|
878
|
+
state: { /* ... */ },
|
|
879
|
+
}}
|
|
880
|
+
mailingAddressSame={{
|
|
881
|
+
checked: formik.values.mailing_same_as_residential,
|
|
882
|
+
onChange: (checked) =>
|
|
883
|
+
formik.setFieldValue('mailing_same_as_residential', checked),
|
|
884
|
+
}}
|
|
885
|
+
onSubmit={formik.handleSubmit}
|
|
886
|
+
/>
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
#### HealthInformationForm
|
|
890
|
+
|
|
891
|
+
Collects health measurements and questions with gender-specific support.
|
|
892
|
+
|
|
893
|
+
```tsx
|
|
894
|
+
import { HealthInformationForm } from 'igloo-d2c-components'
|
|
895
|
+
|
|
896
|
+
<HealthInformationForm
|
|
897
|
+
renderField={renderField}
|
|
898
|
+
measurementFields={{
|
|
899
|
+
weight: {
|
|
900
|
+
name: 'weight',
|
|
901
|
+
label: 'Weight (kg)',
|
|
902
|
+
type: 'number',
|
|
903
|
+
value: formik.values.weight,
|
|
904
|
+
inputProps: { min: 20, max: 300 },
|
|
905
|
+
onChange: formik.handleChange,
|
|
906
|
+
},
|
|
907
|
+
height: { /* ... */ },
|
|
908
|
+
}}
|
|
909
|
+
healthQuestions={[
|
|
910
|
+
{
|
|
911
|
+
question: 'Have you ever had any ongoing or past health conditions?',
|
|
912
|
+
questionNumber: 1,
|
|
913
|
+
name: 'health_conditions',
|
|
914
|
+
value: formik.values.health_conditions,
|
|
915
|
+
onChange: (value) => formik.setFieldValue('health_conditions', value),
|
|
916
|
+
},
|
|
917
|
+
]}
|
|
918
|
+
onSubmit={formik.handleSubmit}
|
|
919
|
+
/>
|
|
920
|
+
```
|
|
420
921
|
|
|
421
922
|
---
|
|
422
923
|
|
|
@@ -470,6 +971,20 @@ function MyComponent() {
|
|
|
470
971
|
}
|
|
471
972
|
```
|
|
472
973
|
|
|
974
|
+
#### useTenantLogo()
|
|
975
|
+
|
|
976
|
+
Get tenant logo URL.
|
|
977
|
+
|
|
978
|
+
```tsx
|
|
979
|
+
import { useTenantLogo } from 'igloo-d2c-components'
|
|
980
|
+
|
|
981
|
+
function MyComponent() {
|
|
982
|
+
const logo = useTenantLogo() // Default logo
|
|
983
|
+
const darkLogo = useTenantLogo('dark') // Dark variant
|
|
984
|
+
return <img src={logo} alt="Logo" />
|
|
985
|
+
}
|
|
986
|
+
```
|
|
987
|
+
|
|
473
988
|
### Utility Functions
|
|
474
989
|
|
|
475
990
|
#### getTenantTheme()
|
|
@@ -483,8 +998,6 @@ const theme = getTenantTheme('igloo')
|
|
|
483
998
|
console.log(theme.palette.primary.main) // '#5656F6'
|
|
484
999
|
```
|
|
485
1000
|
|
|
486
|
-
**Throws:** Error if tenant ID is invalid
|
|
487
|
-
|
|
488
1001
|
#### isValidTenantId()
|
|
489
1002
|
|
|
490
1003
|
Type guard to check if a string is a valid tenant ID.
|
|
@@ -519,15 +1032,348 @@ const color = getThemeColor(theme, 'primary.main', '#000')
|
|
|
519
1032
|
// Returns theme.palette.primary.main or '#000' if not found
|
|
520
1033
|
```
|
|
521
1034
|
|
|
522
|
-
|
|
1035
|
+
---
|
|
523
1036
|
|
|
524
|
-
|
|
1037
|
+
## 📦 Asset Management
|
|
1038
|
+
|
|
1039
|
+
### Asset Organization
|
|
1040
|
+
|
|
1041
|
+
```
|
|
1042
|
+
d2c-component-library/src/assets/
|
|
1043
|
+
├── icons/ # Common UI icons
|
|
1044
|
+
│ ├── alert.svg
|
|
1045
|
+
│ ├── arrow-down.svg
|
|
1046
|
+
│ ├── close.svg
|
|
1047
|
+
│ ├── facebook.svg
|
|
1048
|
+
│ ├── instagram.svg
|
|
1049
|
+
│ ├── youtube.svg
|
|
1050
|
+
│ └── index.ts # Icon path utilities
|
|
1051
|
+
├── tenants/ # Tenant-specific assets
|
|
1052
|
+
│ ├── igloo/logo.svg
|
|
1053
|
+
│ ├── cimb/logo.svg
|
|
1054
|
+
│ └── ammetlife/logo.svg
|
|
1055
|
+
└── index.ts # Main asset exports
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
### Asset Flow Architecture
|
|
1059
|
+
|
|
1060
|
+
```
|
|
1061
|
+
┌─────────────────────────────────────────────────────┐
|
|
1062
|
+
│ ASSET MANAGEMENT ARCHITECTURE │
|
|
1063
|
+
├─────────────────────────────────────────────────────┤
|
|
1064
|
+
│ │
|
|
1065
|
+
│ d2c-component-library/ │
|
|
1066
|
+
│ └── src/assets/ │
|
|
1067
|
+
│ ├── icons/ → Common UI icons │
|
|
1068
|
+
│ └── tenants/ → Tenant logos │
|
|
1069
|
+
│ ├── igloo/logo.svg │
|
|
1070
|
+
│ ├── cimb/logo.svg │
|
|
1071
|
+
│ └── ammetlife/logo.svg │
|
|
1072
|
+
│ │
|
|
1073
|
+
│ BUILD ⬇️ │
|
|
1074
|
+
│ dist/assets/ → Published with library │
|
|
1075
|
+
│ │
|
|
1076
|
+
│ INSTALL ⬇️ │
|
|
1077
|
+
│ node_modules/igloo-d2c-components/dist/assets/ │
|
|
1078
|
+
│ │
|
|
1079
|
+
│ COPY (yarn copy-assets) ⬇️ │
|
|
1080
|
+
│ public/assets/ → Served by UMI │
|
|
1081
|
+
│ │
|
|
1082
|
+
└─────────────────────────────────────────────────────┘
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
### Using Assets
|
|
525
1086
|
|
|
526
|
-
```
|
|
527
|
-
|
|
1087
|
+
```typescript
|
|
1088
|
+
// Get Tenant Logo
|
|
1089
|
+
import { useTenantLogo } from 'igloo-d2c-components'
|
|
528
1090
|
|
|
529
|
-
|
|
530
|
-
|
|
1091
|
+
function MyComponent() {
|
|
1092
|
+
const logo = useTenantLogo() // Default logo
|
|
1093
|
+
const darkLogo = useTenantLogo('dark') // Dark variant
|
|
1094
|
+
return <img src={logo} alt="Logo" />
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// Get Icon Paths
|
|
1098
|
+
import { ICON_PATHS, getIconPath } from 'igloo-d2c-components'
|
|
1099
|
+
<img src={ICON_PATHS.facebook} alt="Facebook" />
|
|
1100
|
+
<img src={getIconPath('instagram')} alt="Instagram" />
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
### Asset Distribution Strategy
|
|
1104
|
+
|
|
1105
|
+
| Asset Type | Location | Reason |
|
|
1106
|
+
| --------------------- | ------------------- | --------------------------- |
|
|
1107
|
+
| **Generic UI Icons** | Library | Reusable across projects |
|
|
1108
|
+
| **Tenant Logos** | Library (via theme) | Centralized management |
|
|
1109
|
+
| **Insurer Logos** | CDN | Shared, updated by partners |
|
|
1110
|
+
| **Marketing Banners** | Application | Frequent changes |
|
|
1111
|
+
| **Documents (PDFs)** | CDN | Large, rarely change |
|
|
1112
|
+
|
|
1113
|
+
### Logo Rendering in Applications
|
|
1114
|
+
|
|
1115
|
+
**Important**: Assets need to be copied to the `public/` folder for UMI to serve them:
|
|
1116
|
+
|
|
1117
|
+
```bash
|
|
1118
|
+
# In consuming application
|
|
1119
|
+
yarn copy-assets # Copies library assets to public/assets/
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
The theme paths reference `/assets/tenants/{tenant}/logo.svg` which maps to:
|
|
1123
|
+
|
|
1124
|
+
- Theme config: `logo: '/assets/tenants/igloo/logo.svg'`
|
|
1125
|
+
- File location: `public/assets/tenants/igloo/logo.svg`
|
|
1126
|
+
- Browser URL: `http://localhost:8001/assets/tenants/igloo/logo.svg`
|
|
1127
|
+
|
|
1128
|
+
---
|
|
1129
|
+
|
|
1130
|
+
## 🔌 Integration Guide
|
|
1131
|
+
|
|
1132
|
+
### Multi-Tenant Architecture
|
|
1133
|
+
|
|
1134
|
+
#### Tenant Configuration Structure
|
|
1135
|
+
|
|
1136
|
+
```
|
|
1137
|
+
config/tenants/
|
|
1138
|
+
├── index.ts # Tenant registry and utility functions
|
|
1139
|
+
├── types.ts # TypeScript interfaces
|
|
1140
|
+
├── igloo.ts # Igloo tenant configuration
|
|
1141
|
+
├── ammetlife.ts # AmmetLife tenant configuration
|
|
1142
|
+
└── cimb.ts # CIMB tenant configuration
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
#### Tenant Configuration Example
|
|
1146
|
+
|
|
1147
|
+
```typescript
|
|
1148
|
+
// config/tenants/igloo.ts
|
|
1149
|
+
import { iglooTheme } from 'igloo-d2c-components'
|
|
1150
|
+
import { TenantConfig } from './types'
|
|
1151
|
+
|
|
1152
|
+
const iglooConfig: TenantConfig = {
|
|
1153
|
+
id: 'igloo',
|
|
1154
|
+
name: 'igloo',
|
|
1155
|
+
displayName: 'Igloo',
|
|
1156
|
+
domain: 'igloo.co.id',
|
|
1157
|
+
|
|
1158
|
+
theme: iglooTheme, // ← Centralized theme from component library
|
|
1159
|
+
|
|
1160
|
+
features: {
|
|
1161
|
+
showPAMenu: true,
|
|
1162
|
+
enableAIChatbot: true,
|
|
1163
|
+
showWorkshopEntryPoint: false,
|
|
1164
|
+
enableFreeAddons: false,
|
|
1165
|
+
},
|
|
1166
|
+
|
|
1167
|
+
routes: {
|
|
1168
|
+
enabled: ['car', 'motorbike', 'health', 'life', 'travel', 'pet'],
|
|
1169
|
+
disabled: [],
|
|
1170
|
+
},
|
|
1171
|
+
|
|
1172
|
+
branding: {
|
|
1173
|
+
companyName: 'Igloo',
|
|
1174
|
+
supportEmail: 'hello@iglooinsure.com',
|
|
1175
|
+
supportPhone: '+62 21 5022 0888',
|
|
1176
|
+
},
|
|
1177
|
+
|
|
1178
|
+
integrations: {
|
|
1179
|
+
gtmCode: 'GTM-5RHHNVQ',
|
|
1180
|
+
gaCode: 'G-QQV6F41YPJ',
|
|
1181
|
+
},
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export default iglooConfig
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
#### AmmetLife Custom Homepage
|
|
1188
|
+
|
|
1189
|
+
AmMetLife uses a custom homepage that displays the life insurance landing page:
|
|
1190
|
+
|
|
1191
|
+
```typescript
|
|
1192
|
+
// config/tenants/ammetlife.ts
|
|
1193
|
+
customRoutes: [
|
|
1194
|
+
{
|
|
1195
|
+
path: '/',
|
|
1196
|
+
exact: true,
|
|
1197
|
+
component: '@/pages/life-landing-page/index.tsx',
|
|
1198
|
+
},
|
|
1199
|
+
]
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
### Checkout Flow Integration
|
|
1203
|
+
|
|
1204
|
+
#### Complete 3-Step Checkout
|
|
1205
|
+
|
|
1206
|
+
The library provides components for a complete checkout flow:
|
|
1207
|
+
|
|
1208
|
+
1. **Personal Information** - 11 fields + 2 consent checkboxes
|
|
1209
|
+
2. **Contact Details** - 6 address fields + mailing checkbox
|
|
1210
|
+
3. **Health Information** - 2 measurements + health questions (gender-specific)
|
|
1211
|
+
|
|
1212
|
+
#### Session Storage Requirements
|
|
1213
|
+
|
|
1214
|
+
```typescript
|
|
1215
|
+
// Required before navigating to checkout
|
|
1216
|
+
session.setItem('plan', {
|
|
1217
|
+
name: 'Plan A',
|
|
1218
|
+
premiumInfo: { currency: 'RM', monthlyAmount: '25' }
|
|
1219
|
+
});
|
|
1220
|
+
|
|
1221
|
+
session.setItem('product', {
|
|
1222
|
+
name: 'LIFE BYOND',
|
|
1223
|
+
logoUrl: 'url-to-logo'
|
|
1224
|
+
});
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
#### Navigation Flow
|
|
1228
|
+
|
|
1229
|
+
```
|
|
1230
|
+
PDP (/en/ammetlife-pdp)
|
|
1231
|
+
↓ Click "Buy now"
|
|
1232
|
+
Checkout Step 1/3 (Personal Info) ← Back → PDP
|
|
1233
|
+
↓ Click "Next"
|
|
1234
|
+
Checkout Step 2/3 (Contact Details) ← Back → Step 1
|
|
1235
|
+
↓ Click "Next"
|
|
1236
|
+
Checkout Step 3/3 (Health Information) ← Back → Step 2
|
|
1237
|
+
↓ Click "Submit"
|
|
1238
|
+
Payment (/en/payment-options)
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
#### Back Button Logic
|
|
1242
|
+
|
|
1243
|
+
```typescript
|
|
1244
|
+
const handleBack = () => {
|
|
1245
|
+
if (currentStep === 0) {
|
|
1246
|
+
// On first step, redirect to PDP
|
|
1247
|
+
window.location.href = `/${currentLocale}/ammetlife-pdp`;
|
|
1248
|
+
} else {
|
|
1249
|
+
// On other steps, go to previous step
|
|
1250
|
+
setCurrentStep(currentStep - 1);
|
|
1251
|
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
#### Validation Rules
|
|
1257
|
+
|
|
1258
|
+
**Personal Information:**
|
|
1259
|
+
|
|
1260
|
+
- Full name: minimum 2 characters
|
|
1261
|
+
- NRIC: numbers and dashes only
|
|
1262
|
+
- DOB: 30 days to 80 years old
|
|
1263
|
+
- Bank account: numbers only
|
|
1264
|
+
- Bank confirmation: must be checked
|
|
1265
|
+
|
|
1266
|
+
**Contact Details:**
|
|
1267
|
+
|
|
1268
|
+
- Phone: 9-14 digits
|
|
1269
|
+
- Email: valid format
|
|
1270
|
+
- Address: minimum 10 characters
|
|
1271
|
+
- Postal code: exactly 5 digits
|
|
1272
|
+
|
|
1273
|
+
**Health Information:**
|
|
1274
|
+
|
|
1275
|
+
- Weight: 20-300 kg
|
|
1276
|
+
- Height: 50-250 cm
|
|
1277
|
+
- All questions: must select Yes or No
|
|
1278
|
+
|
|
1279
|
+
### Recommendations Feature
|
|
1280
|
+
|
|
1281
|
+
#### User Flow
|
|
1282
|
+
|
|
1283
|
+
```
|
|
1284
|
+
1. User sees "See my recommendations" button
|
|
1285
|
+
↓ User clicks
|
|
1286
|
+
2. Mobile drawer slides up from bottom (95vh height)
|
|
1287
|
+
↓
|
|
1288
|
+
3. Drawer shows:
|
|
1289
|
+
- Toggle: Domestic/International
|
|
1290
|
+
- 5 Questions with selectable options
|
|
1291
|
+
- Next button
|
|
1292
|
+
↓ User answers questions
|
|
1293
|
+
4. User clicks "Next" button
|
|
1294
|
+
↓
|
|
1295
|
+
5. Data collected, drawer closes, recommendations shown
|
|
1296
|
+
```
|
|
1297
|
+
|
|
1298
|
+
#### Implementation
|
|
1299
|
+
|
|
1300
|
+
```typescript
|
|
1301
|
+
import { TravelRecommendations } from '@/components/recommendations';
|
|
1302
|
+
import { RecommendationsButton } from '@/components/recommendations/recommendations-button';
|
|
1303
|
+
|
|
1304
|
+
export default function MyPage() {
|
|
1305
|
+
const [showRecommendations, setShowRecommendations] = React.useState(false);
|
|
1306
|
+
|
|
1307
|
+
return (
|
|
1308
|
+
<div>
|
|
1309
|
+
<RecommendationsButton
|
|
1310
|
+
onClick={() => setShowRecommendations(true)}
|
|
1311
|
+
/>
|
|
1312
|
+
|
|
1313
|
+
<TravelRecommendations
|
|
1314
|
+
open={showRecommendations}
|
|
1315
|
+
onClose={() => setShowRecommendations(false)}
|
|
1316
|
+
onSubmit={(data) => {
|
|
1317
|
+
console.log('User selected:', data);
|
|
1318
|
+
}}
|
|
1319
|
+
/>
|
|
1320
|
+
</div>
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1325
|
+
#### Data Structure
|
|
1326
|
+
|
|
1327
|
+
```typescript
|
|
1328
|
+
interface TravelRecommendationsData {
|
|
1329
|
+
travelType: 'domestic' | 'international';
|
|
1330
|
+
selectedPlan: string;
|
|
1331
|
+
monthlyIncome: string;
|
|
1332
|
+
monthlyExpenses: string;
|
|
1333
|
+
currentCoverage: string;
|
|
1334
|
+
employerCoverage: string;
|
|
1335
|
+
}
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
### Header Integration
|
|
1339
|
+
|
|
1340
|
+
#### NewHeader Implementation
|
|
1341
|
+
|
|
1342
|
+
The NewHeader component provides a simplified header with mobile drawer navigation.
|
|
1343
|
+
|
|
1344
|
+
**Features:**
|
|
1345
|
+
|
|
1346
|
+
1. **Product Navigation** - Dynamically loaded from navLinks
|
|
1347
|
+
2. **User Authentication** - Login/Logout flow
|
|
1348
|
+
3. **Additional Links** - Partnership, About Us, Blog
|
|
1349
|
+
4. **Language Selector** - EN/ID with cookie persistence
|
|
1350
|
+
5. **Analytics** - Google Analytics integration
|
|
1351
|
+
|
|
1352
|
+
**Performance Improvement:**
|
|
1353
|
+
|
|
1354
|
+
| Metric | Before | After |
|
|
1355
|
+
| -------------- | --------- | --------- |
|
|
1356
|
+
| Component size | 860 lines | 200 lines |
|
|
1357
|
+
| Bundle size | ~45KB | ~15KB |
|
|
1358
|
+
| Props count | 30+ | 9 |
|
|
1359
|
+
|
|
1360
|
+
### Routing Guide
|
|
1361
|
+
|
|
1362
|
+
#### Route Pattern
|
|
1363
|
+
|
|
1364
|
+
```
|
|
1365
|
+
/:locale/life-checkout
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
#### Navigation with Locale
|
|
1369
|
+
|
|
1370
|
+
```typescript
|
|
1371
|
+
// ✅ CORRECT - With locale
|
|
1372
|
+
const { currentLocale } = local.getItem('globalState');
|
|
1373
|
+
window.location.href = `/${currentLocale}/life-checkout`;
|
|
1374
|
+
|
|
1375
|
+
// ❌ WRONG - Without locale
|
|
1376
|
+
window.location.href = '/life-checkout';
|
|
531
1377
|
```
|
|
532
1378
|
|
|
533
1379
|
---
|
|
@@ -540,6 +1386,7 @@ const vars = createThemeCSSVariables(theme, '--my-app')
|
|
|
540
1386
|
- **Yarn**: `^1.22.0` (recommended) or npm
|
|
541
1387
|
|
|
542
1388
|
Check your version:
|
|
1389
|
+
|
|
543
1390
|
```bash
|
|
544
1391
|
node --version # Should be 16.20.0 - 18.x
|
|
545
1392
|
yarn --version # Should be 1.22.x
|
|
@@ -594,22 +1441,11 @@ dist/
|
|
|
594
1441
|
├── esm/
|
|
595
1442
|
│ ├── index.js # ES Module bundle (unminified, ES2015)
|
|
596
1443
|
│ └── index.js.map # Source map
|
|
597
|
-
|
|
598
|
-
|
|
1444
|
+
├── types/
|
|
1445
|
+
│ └── index.d.ts # TypeScript definitions
|
|
1446
|
+
└── assets/ # Copied assets
|
|
599
1447
|
```
|
|
600
1448
|
|
|
601
|
-
**Why unminified?**
|
|
602
|
-
- ✅ Consuming apps handle minification
|
|
603
|
-
- ✅ Better debugging experience
|
|
604
|
-
- ✅ Better tree-shaking
|
|
605
|
-
- ✅ No impact on final bundle size
|
|
606
|
-
|
|
607
|
-
**Why ES2015?**
|
|
608
|
-
- ✅ Maximum compatibility with older webpack configs
|
|
609
|
-
- ✅ No babel-loader required in consuming apps
|
|
610
|
-
- ✅ Optional chaining (`?.`) transpiled to verbose checks
|
|
611
|
-
- ✅ Works with webpack 4+
|
|
612
|
-
|
|
613
1449
|
### Project Structure
|
|
614
1450
|
|
|
615
1451
|
```
|
|
@@ -618,7 +1454,13 @@ d2c-component-library/
|
|
|
618
1454
|
│ ├── components/ # Component implementations
|
|
619
1455
|
│ │ ├── Button/
|
|
620
1456
|
│ │ ├── Card/
|
|
621
|
-
│ │
|
|
1457
|
+
│ │ ├── Banner/
|
|
1458
|
+
│ │ ├── NewHeader/
|
|
1459
|
+
│ │ ├── RecommendationsDrawer/
|
|
1460
|
+
│ │ ├── ProductSelectionDrawer/
|
|
1461
|
+
│ │ ├── CheckoutHeader/
|
|
1462
|
+
│ │ ├── PersonalInformationForm/
|
|
1463
|
+
│ │ └── ...
|
|
622
1464
|
│ ├── context/
|
|
623
1465
|
│ │ └── TenantThemeContext.tsx
|
|
624
1466
|
│ ├── themes/
|
|
@@ -626,7 +1468,9 @@ d2c-component-library/
|
|
|
626
1468
|
│ ├── types/
|
|
627
1469
|
│ │ └── tenant.ts # TypeScript types
|
|
628
1470
|
│ ├── utils/
|
|
629
|
-
│ │
|
|
1471
|
+
│ │ ├── theme.ts # Theme utilities
|
|
1472
|
+
│ │ └── assets.ts # Asset utilities
|
|
1473
|
+
│ ├── assets/ # UI icons and tenant logos
|
|
630
1474
|
│ └── index.ts # Main exports
|
|
631
1475
|
├── dist/ # Build output (generated)
|
|
632
1476
|
├── examples/
|
|
@@ -635,8 +1479,129 @@ d2c-component-library/
|
|
|
635
1479
|
├── rollup.config.cjs # Rollup build config
|
|
636
1480
|
├── tsconfig.json # TypeScript config
|
|
637
1481
|
├── package.json
|
|
638
|
-
|
|
639
|
-
|
|
1482
|
+
└── README.md # This file
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
---
|
|
1486
|
+
|
|
1487
|
+
## 📖 Storybook
|
|
1488
|
+
|
|
1489
|
+
The library includes Storybook for component documentation and testing.
|
|
1490
|
+
|
|
1491
|
+
### Running Storybook
|
|
1492
|
+
|
|
1493
|
+
```bash
|
|
1494
|
+
# Start Storybook dev server
|
|
1495
|
+
yarn storybook
|
|
1496
|
+
# Opens at http://localhost:6006
|
|
1497
|
+
|
|
1498
|
+
# Build static Storybook
|
|
1499
|
+
yarn build-storybook
|
|
1500
|
+
# Output in storybook-static/
|
|
1501
|
+
```
|
|
1502
|
+
|
|
1503
|
+
### Available Stories
|
|
1504
|
+
|
|
1505
|
+
**NewHeader Stories (12 scenarios):**
|
|
1506
|
+
|
|
1507
|
+
1. Default - Basic header with Igloo branding
|
|
1508
|
+
2. Authenticated User - Header with logged-in user menu
|
|
1509
|
+
3. Mobile View - Responsive mobile layout
|
|
1510
|
+
4. CIMB Tenant - CIMB branding
|
|
1511
|
+
5. AmMetLife Tenant - AmMetLife branding
|
|
1512
|
+
6. Minimal Header - Bare-bones implementation
|
|
1513
|
+
7. Custom Drawer Content - Advanced customization
|
|
1514
|
+
8. Many Menu Items - Stress test with scrolling
|
|
1515
|
+
9. Without Logo - Edge case testing
|
|
1516
|
+
10. With Internationalization - i18n integration
|
|
1517
|
+
11. All Tenants Comparison - Side-by-side view
|
|
1518
|
+
12. Responsive Demo - Interactive responsive testing
|
|
1519
|
+
|
|
1520
|
+
**Other Component Stories:**
|
|
1521
|
+
|
|
1522
|
+
- RecommendationsDrawer - Complete questionnaire flow
|
|
1523
|
+
- ProductSelectionDrawer - Product grid selection
|
|
1524
|
+
- CheckoutHeader - Progress and product display
|
|
1525
|
+
- All checkout components
|
|
1526
|
+
|
|
1527
|
+
### Keyboard Shortcuts
|
|
1528
|
+
|
|
1529
|
+
| Key | Action |
|
|
1530
|
+
| --- | ------------------- |
|
|
1531
|
+
| `F` | Toggle fullscreen |
|
|
1532
|
+
| `S` | Toggle sidebar |
|
|
1533
|
+
| `A` | Toggle addons panel |
|
|
1534
|
+
| `T` | Toggle toolbar |
|
|
1535
|
+
| `D` | Toggle dark mode |
|
|
1536
|
+
| `/` | Search stories |
|
|
1537
|
+
|
|
1538
|
+
---
|
|
1539
|
+
|
|
1540
|
+
## 🔧 Build Pipeline
|
|
1541
|
+
|
|
1542
|
+
### Problems Solved
|
|
1543
|
+
|
|
1544
|
+
1. **Module parse error**: Webpack couldn't parse igloo-d2c-components ESM format
|
|
1545
|
+
2. **Source map error**: Terser plugin couldn't process source maps
|
|
1546
|
+
|
|
1547
|
+
### Solutions Applied
|
|
1548
|
+
|
|
1549
|
+
#### 1. Library: Disabled Source Maps
|
|
1550
|
+
|
|
1551
|
+
```javascript
|
|
1552
|
+
// rollup.config.cjs
|
|
1553
|
+
output: [
|
|
1554
|
+
{
|
|
1555
|
+
file: packageJson.main,
|
|
1556
|
+
format: 'cjs',
|
|
1557
|
+
sourcemap: false, // ✅ Disabled
|
|
1558
|
+
exports: 'named',
|
|
1559
|
+
banner: '"use client"',
|
|
1560
|
+
},
|
|
1561
|
+
]
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
#### 2. Consumer App: Webpack Configuration
|
|
1565
|
+
|
|
1566
|
+
```typescript
|
|
1567
|
+
// .umirc.ts
|
|
1568
|
+
chainWebpack: (memo, { type, webpack }) => {
|
|
1569
|
+
// Prefer CommonJS over ESM
|
|
1570
|
+
memo.resolve.mainFields.clear().add('main').add('module').add('browser');
|
|
1571
|
+
|
|
1572
|
+
// Include igloo-d2c-components in babel transpilation
|
|
1573
|
+
memo.module
|
|
1574
|
+
.rule('js')
|
|
1575
|
+
.include.add(/node_modules[\\/]igloo-d2c-components/)
|
|
1576
|
+
.end();
|
|
1577
|
+
}
|
|
1578
|
+
```
|
|
1579
|
+
|
|
1580
|
+
### CI/CD Pipeline Options
|
|
1581
|
+
|
|
1582
|
+
**Option A: Publish to npm (Recommended)**
|
|
1583
|
+
|
|
1584
|
+
```bash
|
|
1585
|
+
cd d2c-component-library
|
|
1586
|
+
npm publish --access public
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
**Option B: Use Git URL**
|
|
1590
|
+
|
|
1591
|
+
```json
|
|
1592
|
+
{
|
|
1593
|
+
"igloo-d2c-components": "git+https://gitlab.com/axinan/fe/d2c-component-library.git#main"
|
|
1594
|
+
}
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
**Option C: Multi-Repo CI/CD**
|
|
1598
|
+
|
|
1599
|
+
```yaml
|
|
1600
|
+
before_script:
|
|
1601
|
+
- cd ..
|
|
1602
|
+
- git clone https://gitlab.com/axinan/fe/d2c-component-library.git
|
|
1603
|
+
- cd d2c-component-library && yarn install && yarn build
|
|
1604
|
+
- cd ../b2c-web-demo && yarn install
|
|
640
1605
|
```
|
|
641
1606
|
|
|
642
1607
|
---
|
|
@@ -646,21 +1611,21 @@ d2c-component-library/
|
|
|
646
1611
|
### Prerequisites
|
|
647
1612
|
|
|
648
1613
|
1. **Ensure clean working directory:**
|
|
1614
|
+
|
|
649
1615
|
```bash
|
|
650
1616
|
git status # Should be clean
|
|
651
1617
|
```
|
|
652
1618
|
|
|
653
1619
|
2. **Update version in package.json:**
|
|
1620
|
+
|
|
654
1621
|
```json
|
|
655
1622
|
{
|
|
656
1623
|
"version": "1.0.7"
|
|
657
1624
|
}
|
|
658
1625
|
```
|
|
659
1626
|
|
|
660
|
-
3. **
|
|
661
|
-
Document changes in the new version section
|
|
1627
|
+
3. **Build the library:**
|
|
662
1628
|
|
|
663
|
-
4. **Build the library:**
|
|
664
1629
|
```bash
|
|
665
1630
|
yarn build
|
|
666
1631
|
```
|
|
@@ -668,15 +1633,13 @@ d2c-component-library/
|
|
|
668
1633
|
### Publishing to NPM
|
|
669
1634
|
|
|
670
1635
|
**Set up NPM token:**
|
|
1636
|
+
|
|
671
1637
|
```bash
|
|
672
|
-
# Get token from https://www.npmjs.com/settings/YOUR_USERNAME/tokens
|
|
673
1638
|
export NPM_AUTH_TOKEN="npm_your_actual_token"
|
|
674
|
-
|
|
675
|
-
# Or add to ~/.npmrc globally
|
|
676
|
-
//registry.npmjs.org/:_authToken=npm_your_token
|
|
677
1639
|
```
|
|
678
1640
|
|
|
679
1641
|
**Publish:**
|
|
1642
|
+
|
|
680
1643
|
```bash
|
|
681
1644
|
# Automated script with safety checks
|
|
682
1645
|
./publish-to-npm.sh
|
|
@@ -686,137 +1649,22 @@ yarn build
|
|
|
686
1649
|
npm publish --access public
|
|
687
1650
|
```
|
|
688
1651
|
|
|
689
|
-
### Publishing to GitLab Package Registry
|
|
690
|
-
|
|
691
|
-
**Set up GitLab token:**
|
|
692
|
-
```bash
|
|
693
|
-
# Get token from https://gitlab.com/-/profile/personal_access_tokens
|
|
694
|
-
# Scopes: api, read_registry, write_registry
|
|
695
|
-
export GITLAB_NPM_TOKEN="glpat-your-token"
|
|
696
|
-
```
|
|
697
|
-
|
|
698
|
-
**Configure `.npmrc` for GitLab:**
|
|
699
|
-
```ini
|
|
700
|
-
@igloo:registry=https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/
|
|
701
|
-
//gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/:_authToken=${GITLAB_NPM_TOKEN}
|
|
702
|
-
```
|
|
703
|
-
|
|
704
|
-
**Publish:**
|
|
705
|
-
```bash
|
|
706
|
-
yarn build
|
|
707
|
-
npm publish
|
|
708
|
-
```
|
|
709
|
-
|
|
710
|
-
### CI/CD Publishing
|
|
711
|
-
|
|
712
|
-
The library includes a GitLab CI/CD configuration (`.gitlab-ci.yml`) that automatically:
|
|
713
|
-
|
|
714
|
-
1. **Runs on main branch** or tags
|
|
715
|
-
2. **Lints and type-checks** code
|
|
716
|
-
3. **Builds** the library
|
|
717
|
-
4. **Publishes** to registry (if tag)
|
|
718
|
-
|
|
719
|
-
**Trigger CI/CD publish:**
|
|
720
|
-
```bash
|
|
721
|
-
# Create and push a tag
|
|
722
|
-
git tag v1.0.7
|
|
723
|
-
git push origin v1.0.7
|
|
724
|
-
```
|
|
725
|
-
|
|
726
1652
|
### Version Management
|
|
727
1653
|
|
|
728
1654
|
**Semantic Versioning:**
|
|
1655
|
+
|
|
729
1656
|
- **Major** (1.0.0 → 2.0.0): Breaking changes
|
|
730
1657
|
- **Minor** (1.0.0 → 1.1.0): New features, backwards compatible
|
|
731
1658
|
- **Patch** (1.0.0 → 1.0.1): Bug fixes
|
|
732
1659
|
|
|
733
1660
|
**Update version:**
|
|
734
|
-
```bash
|
|
735
|
-
# Manually in package.json
|
|
736
|
-
"version": "1.0.7"
|
|
737
1661
|
|
|
738
|
-
|
|
1662
|
+
```bash
|
|
739
1663
|
npm version patch # 1.0.6 → 1.0.7
|
|
740
1664
|
npm version minor # 1.0.6 → 1.1.0
|
|
741
1665
|
npm version major # 1.0.6 → 2.0.0
|
|
742
1666
|
```
|
|
743
1667
|
|
|
744
|
-
### Post-Publishing
|
|
745
|
-
|
|
746
|
-
After publishing:
|
|
747
|
-
|
|
748
|
-
1. **Tag the release:**
|
|
749
|
-
```bash
|
|
750
|
-
git tag v1.0.7
|
|
751
|
-
git push origin v1.0.7
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
2. **Update consuming apps:**
|
|
755
|
-
```bash
|
|
756
|
-
cd ../b2c-web-demo
|
|
757
|
-
yarn upgrade igloo-d2c-components@latest
|
|
758
|
-
```
|
|
759
|
-
|
|
760
|
-
3. **Announce the release** to the team
|
|
761
|
-
|
|
762
|
-
---
|
|
763
|
-
|
|
764
|
-
## 📖 Storybook
|
|
765
|
-
|
|
766
|
-
The library includes Storybook for component documentation and testing.
|
|
767
|
-
|
|
768
|
-
### Running Storybook
|
|
769
|
-
|
|
770
|
-
```bash
|
|
771
|
-
# Start Storybook dev server
|
|
772
|
-
yarn storybook
|
|
773
|
-
# Opens at http://localhost:6006
|
|
774
|
-
|
|
775
|
-
# Build static Storybook
|
|
776
|
-
yarn build-storybook
|
|
777
|
-
# Output in storybook-static/
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
### Storybook Features
|
|
781
|
-
|
|
782
|
-
- **Component Playground** - Interactive component testing
|
|
783
|
-
- **Props Documentation** - Auto-generated from TypeScript
|
|
784
|
-
- **Theme Switching** - Test with different tenant themes
|
|
785
|
-
- **Responsive Design** - Test different viewports
|
|
786
|
-
- **Accessibility** - Built-in a11y addon
|
|
787
|
-
|
|
788
|
-
### Adding Stories
|
|
789
|
-
|
|
790
|
-
Create a `.stories.tsx` file next to your component:
|
|
791
|
-
|
|
792
|
-
```tsx
|
|
793
|
-
// src/components/MyComponent/MyComponent.stories.tsx
|
|
794
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
795
|
-
import { TenantThemeProvider, iglooTheme } from '../../index'
|
|
796
|
-
import { MyComponent } from './MyComponent'
|
|
797
|
-
|
|
798
|
-
const meta: Meta<typeof MyComponent> = {
|
|
799
|
-
title: 'Components/MyComponent',
|
|
800
|
-
component: MyComponent,
|
|
801
|
-
decorators: [
|
|
802
|
-
(Story) => (
|
|
803
|
-
<TenantThemeProvider tenantId="igloo" theme={iglooTheme}>
|
|
804
|
-
<Story />
|
|
805
|
-
</TenantThemeProvider>
|
|
806
|
-
),
|
|
807
|
-
],
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
export default meta
|
|
811
|
-
type Story = StoryObj<typeof MyComponent>
|
|
812
|
-
|
|
813
|
-
export const Default: Story = {
|
|
814
|
-
args: {
|
|
815
|
-
prop1: 'value1',
|
|
816
|
-
},
|
|
817
|
-
}
|
|
818
|
-
```
|
|
819
|
-
|
|
820
1668
|
---
|
|
821
1669
|
|
|
822
1670
|
## 🔬 Technical Details
|
|
@@ -824,6 +1672,7 @@ export const Default: Story = {
|
|
|
824
1672
|
### Build Configuration
|
|
825
1673
|
|
|
826
1674
|
**Rollup Configuration** (`rollup.config.cjs`):
|
|
1675
|
+
|
|
827
1676
|
```javascript
|
|
828
1677
|
{
|
|
829
1678
|
input: 'src/index.ts',
|
|
@@ -843,19 +1692,6 @@ export const Default: Story = {
|
|
|
843
1692
|
banner: '"use client"',
|
|
844
1693
|
},
|
|
845
1694
|
],
|
|
846
|
-
plugins: [
|
|
847
|
-
peerDepsExternal(),
|
|
848
|
-
resolve(),
|
|
849
|
-
commonjs(),
|
|
850
|
-
typescript({
|
|
851
|
-
tsconfig: './tsconfig.json',
|
|
852
|
-
compilerOptions: {
|
|
853
|
-
declaration: false,
|
|
854
|
-
target: 'ES2015', // For compatibility
|
|
855
|
-
},
|
|
856
|
-
}),
|
|
857
|
-
// NO terser() - libraries should not be minified
|
|
858
|
-
],
|
|
859
1695
|
}
|
|
860
1696
|
```
|
|
861
1697
|
|
|
@@ -881,17 +1717,6 @@ export const Default: Story = {
|
|
|
881
1717
|
}
|
|
882
1718
|
```
|
|
883
1719
|
|
|
884
|
-
### Package Exports
|
|
885
|
-
|
|
886
|
-
```json
|
|
887
|
-
{
|
|
888
|
-
"main": "dist/cjs/index.js",
|
|
889
|
-
"module": "dist/esm/index.js",
|
|
890
|
-
"types": "dist/types/index.d.ts",
|
|
891
|
-
"files": ["dist", "README.md"]
|
|
892
|
-
}
|
|
893
|
-
```
|
|
894
|
-
|
|
895
1720
|
---
|
|
896
1721
|
|
|
897
1722
|
## 🐛 Troubleshooting
|
|
@@ -899,129 +1724,107 @@ export const Default: Story = {
|
|
|
899
1724
|
### Webpack Module Parse Error
|
|
900
1725
|
|
|
901
1726
|
**Error:**
|
|
1727
|
+
|
|
902
1728
|
```
|
|
903
1729
|
Module parse failed: Unexpected token
|
|
904
1730
|
```
|
|
905
1731
|
|
|
906
|
-
**Cause:** Webpack can't parse the library output.
|
|
907
|
-
|
|
908
1732
|
**Solution:**
|
|
909
1733
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
```bash
|
|
918
|
-
cd ../b2c-web-demo
|
|
919
|
-
rm -rf node_modules/igloo-d2c-components
|
|
920
|
-
yarn install
|
|
921
|
-
```
|
|
922
|
-
|
|
923
|
-
**Prevention:** The library is configured to output ES2015 JavaScript which is compatible with webpack 4+. Modern syntax like optional chaining (`?.`) is transpiled to verbose null checks.
|
|
1734
|
+
```bash
|
|
1735
|
+
cd d2c-component-library
|
|
1736
|
+
yarn clean && yarn build
|
|
1737
|
+
cd ../b2c-web-demo
|
|
1738
|
+
rm -rf node_modules/igloo-d2c-components
|
|
1739
|
+
yarn install
|
|
1740
|
+
```
|
|
924
1741
|
|
|
925
1742
|
### Theme Not Found Error
|
|
926
1743
|
|
|
927
1744
|
**Error:**
|
|
1745
|
+
|
|
928
1746
|
```
|
|
929
1747
|
Theme not found for tenant: xxx
|
|
930
1748
|
```
|
|
931
1749
|
|
|
932
1750
|
**Solution:** Use valid tenant IDs: `'igloo'`, `'cimb'`, or `'ammetlife'`.
|
|
933
1751
|
|
|
934
|
-
```typescript
|
|
935
|
-
import { isValidTenantId, getTenantTheme } from 'igloo-d2c-components'
|
|
936
|
-
|
|
937
|
-
if (isValidTenantId(tenantId)) {
|
|
938
|
-
const theme = getTenantTheme(tenantId)
|
|
939
|
-
} else {
|
|
940
|
-
console.error('Invalid tenant ID:', tenantId)
|
|
941
|
-
}
|
|
942
|
-
```
|
|
943
|
-
|
|
944
1752
|
### TypeScript Errors with Imports
|
|
945
1753
|
|
|
946
1754
|
**Error:**
|
|
1755
|
+
|
|
947
1756
|
```
|
|
948
1757
|
Module '"igloo-d2c-components"' has no exported member 'iglooTheme'
|
|
949
1758
|
```
|
|
950
1759
|
|
|
951
1760
|
**Solution:**
|
|
952
1761
|
|
|
953
|
-
1.
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
yarn build
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
2. **Reinstall in consuming app:**
|
|
960
|
-
```bash
|
|
961
|
-
cd ../b2c-web-demo
|
|
962
|
-
yarn remove igloo-d2c-components
|
|
963
|
-
yarn add igloo-d2c-components@file:../d2c-component-library
|
|
964
|
-
```
|
|
965
|
-
|
|
966
|
-
3. **Restart TypeScript server** in your IDE:
|
|
967
|
-
- VS Code: Cmd+Shift+P → "TypeScript: Restart TS Server"
|
|
1762
|
+
1. Rebuild the library: `yarn build`
|
|
1763
|
+
2. Reinstall in consuming app: `yarn install`
|
|
1764
|
+
3. Restart TypeScript server in your IDE
|
|
968
1765
|
|
|
969
1766
|
### Build Failures
|
|
970
1767
|
|
|
971
1768
|
**Error:** Build fails with memory issues
|
|
972
1769
|
|
|
973
1770
|
**Solution:**
|
|
1771
|
+
|
|
974
1772
|
```bash
|
|
975
1773
|
export NODE_OPTIONS="--max-old-space-size=4096"
|
|
976
1774
|
yarn build
|
|
977
1775
|
```
|
|
978
1776
|
|
|
979
|
-
|
|
1777
|
+
### Asset Issues
|
|
980
1778
|
|
|
981
|
-
**
|
|
982
|
-
```bash
|
|
983
|
-
# Check types first
|
|
984
|
-
yarn type-check
|
|
1779
|
+
**Logos not displaying:**
|
|
985
1780
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1781
|
+
1. Run `yarn copy-assets` in consuming app
|
|
1782
|
+
2. Verify assets in `public/assets/tenants/`
|
|
1783
|
+
3. Check theme path: `/assets/tenants/igloo/logo.svg`
|
|
989
1784
|
|
|
990
|
-
###
|
|
1785
|
+
### Routing Issues
|
|
991
1786
|
|
|
992
|
-
**
|
|
993
|
-
|
|
994
|
-
**Solution:** Install peer dependencies in consuming app:
|
|
995
|
-
```bash
|
|
996
|
-
yarn add react@17 react-dom@17 @mui/material@5 @emotion/react @emotion/styled
|
|
997
|
-
```
|
|
1787
|
+
**Issue: 404 on /life-checkout**
|
|
1788
|
+
Use locale prefix: `/en/life-checkout`, not `/life-checkout`
|
|
998
1789
|
|
|
999
1790
|
---
|
|
1000
1791
|
|
|
1001
|
-
##
|
|
1792
|
+
## 📝 Changelog
|
|
1793
|
+
|
|
1794
|
+
### [Unreleased]
|
|
1795
|
+
|
|
1796
|
+
#### Added
|
|
1002
1797
|
|
|
1003
|
-
|
|
1798
|
+
- **CheckoutProgress** - Progress bar component with step indicator
|
|
1799
|
+
- **ProductCard** - Product information card for checkout flows
|
|
1800
|
+
- **CheckoutHeader** - Complete checkout header combining progress and product card
|
|
1801
|
+
- **CheckoutFormButton** - Fixed/floating button for form submission
|
|
1802
|
+
- **HealthQuestionGroup** - Health question component with Yes/No options
|
|
1803
|
+
- **ProductSelectionDrawer** - Mobile-first bottom drawer for product selection
|
|
1804
|
+
- **PersonalInformationForm** - Personal details form component
|
|
1805
|
+
- **ContactDetailsForm** - Contact and address form component
|
|
1806
|
+
- **HealthInformationForm** - Health measurements and questions form
|
|
1807
|
+
- Comprehensive Storybook documentation
|
|
1808
|
+
- Integration guides for multi-tenant architecture
|
|
1004
1809
|
|
|
1005
|
-
1.
|
|
1006
|
-
2. **Use ES2015 features** - Avoid ES2020+ syntax
|
|
1007
|
-
3. **Test in consuming apps** - Test changes in b2c-web-demo
|
|
1008
|
-
4. **Update CHANGELOG** - Document all changes
|
|
1009
|
-
5. **Version appropriately** - Follow semantic versioning
|
|
1810
|
+
### [1.0.1] - 2025-11-11
|
|
1010
1811
|
|
|
1011
|
-
|
|
1812
|
+
#### Changed
|
|
1012
1813
|
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
3. **Use tenantColored prop** - For tenant-specific styling
|
|
1016
|
-
4. **Maintain type safety** - Use provided TypeScript types
|
|
1017
|
-
5. **Extend via composition** - Don't modify library components
|
|
1814
|
+
- Package name configured for public NPM registry
|
|
1815
|
+
- Updated all documentation
|
|
1018
1816
|
|
|
1019
|
-
###
|
|
1817
|
+
### [1.0.0] - 2025-10-31
|
|
1020
1818
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1819
|
+
#### Added
|
|
1820
|
+
|
|
1821
|
+
- Initial release of D2C Component Library
|
|
1822
|
+
- `TenantThemeProvider` - Context provider for tenant theming
|
|
1823
|
+
- Hooks: `useTenantTheme()`, `useTenantId()`, `useIsTenant()`
|
|
1824
|
+
- Components: `Button`, `Card`, `Banner`
|
|
1825
|
+
- Utility functions for theme management
|
|
1826
|
+
- Full TypeScript support
|
|
1827
|
+
- ESM and CommonJS builds
|
|
1025
1828
|
|
|
1026
1829
|
---
|
|
1027
1830
|
|
|
@@ -1031,31 +1834,35 @@ yarn add react@17 react-dom@17 @mui/material@5 @emotion/react @emotion/styled
|
|
|
1031
1834
|
|
|
1032
1835
|
1. **Fork the repository**
|
|
1033
1836
|
2. **Create a feature branch:**
|
|
1837
|
+
|
|
1034
1838
|
```bash
|
|
1035
1839
|
git checkout -b feature/my-new-feature
|
|
1036
1840
|
```
|
|
1841
|
+
|
|
1037
1842
|
3. **Make your changes**
|
|
1038
1843
|
4. **Test thoroughly:**
|
|
1844
|
+
|
|
1039
1845
|
```bash
|
|
1040
1846
|
yarn lint
|
|
1041
1847
|
yarn type-check
|
|
1042
1848
|
yarn build
|
|
1043
1849
|
```
|
|
1850
|
+
|
|
1044
1851
|
5. **Test in consuming app:**
|
|
1852
|
+
|
|
1045
1853
|
```bash
|
|
1046
1854
|
cd ../b2c-web-demo
|
|
1047
1855
|
yarn install
|
|
1048
1856
|
yarn start-igloo-dev
|
|
1049
1857
|
```
|
|
1858
|
+
|
|
1050
1859
|
6. **Commit your changes:**
|
|
1860
|
+
|
|
1051
1861
|
```bash
|
|
1052
1862
|
git commit -m "feat: add new feature"
|
|
1053
1863
|
```
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
git push origin feature/my-new-feature
|
|
1057
|
-
```
|
|
1058
|
-
8. **Create a Pull Request**
|
|
1864
|
+
|
|
1865
|
+
7. **Push and create a Pull Request**
|
|
1059
1866
|
|
|
1060
1867
|
### Commit Message Format
|
|
1061
1868
|
|
|
@@ -1063,13 +1870,10 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
|
1063
1870
|
|
|
1064
1871
|
```
|
|
1065
1872
|
<type>(<scope>): <description>
|
|
1066
|
-
|
|
1067
|
-
[optional body]
|
|
1068
|
-
|
|
1069
|
-
[optional footer]
|
|
1070
1873
|
```
|
|
1071
1874
|
|
|
1072
1875
|
**Types:**
|
|
1876
|
+
|
|
1073
1877
|
- `feat`: New feature
|
|
1074
1878
|
- `fix`: Bug fix
|
|
1075
1879
|
- `docs`: Documentation changes
|
|
@@ -1078,22 +1882,15 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
|
1078
1882
|
- `test`: Test additions/changes
|
|
1079
1883
|
- `chore`: Maintenance tasks
|
|
1080
1884
|
|
|
1081
|
-
**Examples:**
|
|
1082
|
-
```
|
|
1083
|
-
feat(themes): add new tenant theme
|
|
1084
|
-
fix(Button): correct hover state color
|
|
1085
|
-
docs: update installation guide
|
|
1086
|
-
chore: bump version to 1.0.7
|
|
1087
|
-
```
|
|
1088
|
-
|
|
1089
1885
|
### Adding a New Tenant
|
|
1090
1886
|
|
|
1091
1887
|
1. **Add theme to `src/themes/index.ts`:**
|
|
1888
|
+
|
|
1092
1889
|
```typescript
|
|
1093
1890
|
export const newTenantTheme: TenantThemeConfig = {
|
|
1094
1891
|
palette: { /* ... */ },
|
|
1095
1892
|
typography: { /* ... */ },
|
|
1096
|
-
logo: '/assets/
|
|
1893
|
+
logo: '/assets/tenants/newtenant/logo.svg',
|
|
1097
1894
|
favicon: 'https://...',
|
|
1098
1895
|
}
|
|
1099
1896
|
|
|
@@ -1106,18 +1903,26 @@ chore: bump version to 1.0.7
|
|
|
1106
1903
|
```
|
|
1107
1904
|
|
|
1108
1905
|
2. **Update TenantId type in `src/types/tenant.ts`:**
|
|
1906
|
+
|
|
1109
1907
|
```typescript
|
|
1110
1908
|
export type TenantId = 'igloo' | 'cimb' | 'ammetlife' | 'newtenant'
|
|
1111
1909
|
```
|
|
1112
1910
|
|
|
1113
|
-
3. **
|
|
1911
|
+
3. **Add logo asset to `src/assets/tenants/newtenant/`**
|
|
1912
|
+
|
|
1913
|
+
4. **Build and test:**
|
|
1914
|
+
|
|
1114
1915
|
```bash
|
|
1115
1916
|
yarn build
|
|
1116
|
-
cd ../b2c-web-demo
|
|
1117
|
-
yarn install
|
|
1118
1917
|
```
|
|
1119
1918
|
|
|
1120
|
-
|
|
1919
|
+
### Adding New Components
|
|
1920
|
+
|
|
1921
|
+
1. Create component folder in `src/components/`
|
|
1922
|
+
2. Include: `ComponentName.tsx`, `styled.tsx`, `index.ts`
|
|
1923
|
+
3. Add Storybook stories
|
|
1924
|
+
4. Export from `src/index.ts`
|
|
1925
|
+
5. Update documentation
|
|
1121
1926
|
|
|
1122
1927
|
---
|
|
1123
1928
|
|
|
@@ -1135,16 +1940,16 @@ Frontend Engineering Team - Axinan/Igloo
|
|
|
1135
1940
|
|
|
1136
1941
|
## 🔗 Links
|
|
1137
1942
|
|
|
1138
|
-
- **Repository:** https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library
|
|
1139
|
-
- **NPM Package:** https://www.npmjs.com/package/igloo-d2c-components
|
|
1140
|
-
- **Consuming App:** https://gitlab.iglooinsure.com/axinan/fe/b2c-web-demo
|
|
1141
|
-
- **Issue Tracker:** https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library/-/issues
|
|
1943
|
+
- **Repository:** <https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library>
|
|
1944
|
+
- **NPM Package:** <https://www.npmjs.com/package/igloo-d2c-components>
|
|
1945
|
+
- **Consuming App:** <https://gitlab.iglooinsure.com/axinan/fe/b2c-web-demo>
|
|
1142
1946
|
|
|
1143
1947
|
---
|
|
1144
1948
|
|
|
1145
1949
|
## 📝 Quick Reference
|
|
1146
1950
|
|
|
1147
1951
|
### Installation
|
|
1952
|
+
|
|
1148
1953
|
```bash
|
|
1149
1954
|
# Local development
|
|
1150
1955
|
yarn add igloo-d2c-components@file:../d2c-component-library
|
|
@@ -1154,38 +1959,45 @@ yarn add igloo-d2c-components@latest
|
|
|
1154
1959
|
```
|
|
1155
1960
|
|
|
1156
1961
|
### Import Themes
|
|
1962
|
+
|
|
1157
1963
|
```typescript
|
|
1158
1964
|
import { iglooTheme, cimbTheme, ammetlifeTheme, getTenantTheme } from 'igloo-d2c-components'
|
|
1159
1965
|
```
|
|
1160
1966
|
|
|
1161
1967
|
### Import Components
|
|
1968
|
+
|
|
1162
1969
|
```typescript
|
|
1163
|
-
import { Button, Card, Banner, TenantThemeProvider } from 'igloo-d2c-components'
|
|
1970
|
+
import { Button, Card, Banner, TenantThemeProvider, NewHeader, CheckoutHeader } from 'igloo-d2c-components'
|
|
1164
1971
|
```
|
|
1165
1972
|
|
|
1166
1973
|
### Import Hooks
|
|
1974
|
+
|
|
1167
1975
|
```typescript
|
|
1168
|
-
import { useTenantTheme, useTenantId, useIsTenant } from 'igloo-d2c-components'
|
|
1976
|
+
import { useTenantTheme, useTenantId, useIsTenant, useTenantLogo } from 'igloo-d2c-components'
|
|
1169
1977
|
```
|
|
1170
1978
|
|
|
1171
1979
|
### Build & Publish
|
|
1980
|
+
|
|
1172
1981
|
```bash
|
|
1173
1982
|
# Build
|
|
1174
1983
|
yarn build
|
|
1175
1984
|
|
|
1176
1985
|
# Publish to NPM
|
|
1177
1986
|
./publish-to-npm.sh
|
|
1987
|
+
```
|
|
1178
1988
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1989
|
+
### Test All Tenants (in b2c-web-demo)
|
|
1990
|
+
|
|
1991
|
+
```bash
|
|
1992
|
+
yarn start-igloo # Port 8000
|
|
1993
|
+
yarn start-ammetlife # Port 8001
|
|
1994
|
+
yarn start-cimb # Port 8002
|
|
1181
1995
|
```
|
|
1182
1996
|
|
|
1183
1997
|
---
|
|
1184
1998
|
|
|
1185
|
-
**Version:** 1.0.
|
|
1186
|
-
**Last Updated:**
|
|
1999
|
+
**Version:** 1.0.11+
|
|
2000
|
+
**Last Updated:** December 2025
|
|
1187
2001
|
**Node.js:** >=16.20.0 <=18.x
|
|
1188
2002
|
**Target:** ES2015
|
|
1189
2003
|
**Output:** Unminified
|
|
1190
|
-
|
|
1191
|
-
For version history, see [CHANGELOG.md](./CHANGELOG.md)
|