@akinon/pz-click-collect 2.0.0-beta.8 → 2.0.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 +124 -15
- package/README.md +178 -4
- package/package.json +8 -8
- package/src/index.tsx +159 -65
package/CHANGELOG.md
CHANGED
|
@@ -1,39 +1,148 @@
|
|
|
1
1
|
# @akinon/pz-click-collect
|
|
2
2
|
|
|
3
|
-
## 2.0.0
|
|
3
|
+
## 2.0.0
|
|
4
4
|
|
|
5
|
-
## 2.0.0-beta.
|
|
5
|
+
## 2.0.0-beta.27
|
|
6
6
|
|
|
7
|
-
## 2.0.0-beta.
|
|
7
|
+
## 2.0.0-beta.26
|
|
8
|
+
|
|
9
|
+
## 2.0.0-beta.25
|
|
10
|
+
|
|
11
|
+
## 2.0.0-beta.24
|
|
12
|
+
|
|
13
|
+
## 2.0.0-beta.23
|
|
14
|
+
|
|
15
|
+
## 2.0.0-beta.22
|
|
16
|
+
|
|
17
|
+
## 2.0.0-beta.21
|
|
18
|
+
|
|
19
|
+
## 2.0.0-beta.20
|
|
20
|
+
|
|
21
|
+
## 1.126.0
|
|
22
|
+
|
|
23
|
+
## 1.125.2
|
|
24
|
+
|
|
25
|
+
## 1.125.1
|
|
26
|
+
|
|
27
|
+
## 1.125.0
|
|
28
|
+
|
|
29
|
+
## 1.124.0
|
|
30
|
+
|
|
31
|
+
## 1.123.0
|
|
32
|
+
|
|
33
|
+
## 1.122.0
|
|
34
|
+
|
|
35
|
+
## 1.121.0
|
|
36
|
+
|
|
37
|
+
## 1.120.0
|
|
38
|
+
|
|
39
|
+
## 1.119.0
|
|
40
|
+
|
|
41
|
+
## 1.118.0
|
|
42
|
+
|
|
43
|
+
## 1.117.0
|
|
44
|
+
|
|
45
|
+
## 1.116.0
|
|
46
|
+
|
|
47
|
+
## 1.115.0
|
|
48
|
+
|
|
49
|
+
## 1.114.0
|
|
50
|
+
|
|
51
|
+
## 1.113.0
|
|
52
|
+
|
|
53
|
+
## 1.112.0
|
|
54
|
+
|
|
55
|
+
## 1.111.0
|
|
56
|
+
|
|
57
|
+
## 1.110.0
|
|
58
|
+
|
|
59
|
+
## 1.109.0
|
|
60
|
+
|
|
61
|
+
## 1.108.0
|
|
62
|
+
|
|
63
|
+
## 1.107.0
|
|
64
|
+
|
|
65
|
+
## 1.106.0
|
|
66
|
+
|
|
67
|
+
## 1.105.0
|
|
68
|
+
|
|
69
|
+
## 1.104.0
|
|
70
|
+
|
|
71
|
+
## 1.103.0
|
|
72
|
+
|
|
73
|
+
### Minor Changes
|
|
74
|
+
|
|
75
|
+
- b16a370: ZERO-3403: Enhance README.md with detailed Click & Collect component documentation and usage examples
|
|
76
|
+
|
|
77
|
+
## 1.102.0
|
|
78
|
+
|
|
79
|
+
## 1.101.0
|
|
80
|
+
|
|
81
|
+
## 1.100.0
|
|
82
|
+
|
|
83
|
+
## 1.99.0
|
|
84
|
+
|
|
85
|
+
### Minor Changes
|
|
86
|
+
|
|
87
|
+
- d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
|
|
88
|
+
|
|
89
|
+
## 1.98.0
|
|
90
|
+
|
|
91
|
+
## 1.97.0
|
|
92
|
+
|
|
93
|
+
## 1.96.0
|
|
94
|
+
|
|
95
|
+
## 1.95.0
|
|
96
|
+
|
|
97
|
+
## 1.94.0
|
|
8
98
|
|
|
9
99
|
### Minor Changes
|
|
10
100
|
|
|
11
|
-
-
|
|
101
|
+
- 1b4c343: ZERO-3341: Add data-testid for click-collect package
|
|
12
102
|
|
|
13
|
-
##
|
|
103
|
+
## 1.93.0
|
|
14
104
|
|
|
15
|
-
##
|
|
105
|
+
## 1.92.0
|
|
16
106
|
|
|
17
|
-
##
|
|
107
|
+
## 1.91.0
|
|
18
108
|
|
|
19
|
-
##
|
|
109
|
+
## 1.90.0
|
|
20
110
|
|
|
21
111
|
### Minor Changes
|
|
22
112
|
|
|
23
|
-
-
|
|
24
|
-
|
|
113
|
+
- c9b8c6f: ZERO-3374: Add Click & Collect component documentation and enhance type definitions
|
|
114
|
+
|
|
115
|
+
## 1.89.0
|
|
116
|
+
|
|
117
|
+
## 1.88.0
|
|
118
|
+
|
|
119
|
+
## 1.87.0
|
|
25
120
|
|
|
26
|
-
##
|
|
121
|
+
## 1.86.0
|
|
122
|
+
|
|
123
|
+
## 1.85.0
|
|
124
|
+
|
|
125
|
+
## 1.84.0
|
|
27
126
|
|
|
28
127
|
### Minor Changes
|
|
29
128
|
|
|
30
|
-
- ZERO-
|
|
129
|
+
- 624a4eb: ZERO-3276: Update installation instructions across multiple README files to standardize format and improve clarity
|
|
130
|
+
|
|
131
|
+
## 1.83.0
|
|
132
|
+
|
|
133
|
+
## 1.82.0
|
|
134
|
+
|
|
135
|
+
## 1.81.0
|
|
136
|
+
|
|
137
|
+
## 1.80.0
|
|
138
|
+
|
|
139
|
+
## 1.79.0
|
|
31
140
|
|
|
32
|
-
##
|
|
141
|
+
## 1.78.0
|
|
33
142
|
|
|
34
|
-
|
|
143
|
+
## 1.77.0
|
|
35
144
|
|
|
36
|
-
|
|
145
|
+
## 1.76.0
|
|
37
146
|
|
|
38
147
|
## 1.75.0
|
|
39
148
|
|
package/README.md
CHANGED
|
@@ -10,12 +10,186 @@ npx @akinon/projectzero@latest --plugins
|
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# Click & Collect Component
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
| ---------------- | -------- | -------------------------- |
|
|
17
|
-
| addressTypeParam | `string` | Address Type Request Param |
|
|
15
|
+
The ClickCollect component enables customers to choose retail store pickup instead of standard shipping. It integrates deeply with the checkout flow and allows complete UI customization.
|
|
18
16
|
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
- Toggle between delivery to address and retail store pickup
|
|
20
|
+
- City and store selection
|
|
21
|
+
- Fully customizable UI through renderer props
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
|
|
25
|
+
### ClickCollectProps
|
|
26
|
+
|
|
27
|
+
| Properties | Type | Required | Description |
|
|
28
|
+
| --- | --- | --- | --- |
|
|
29
|
+
| addressTypeParam | `string` | Yes | Address Type Request Param |
|
|
30
|
+
| translations | `ClickCollectTranslationsProps` | Yes | Object containing localized strings. |
|
|
31
|
+
| renderer | `ClickCollectRendererProps` | No | Optional UI overrides for component sections. |
|
|
32
|
+
|
|
33
|
+
### ClickCollectTranslationsProps
|
|
34
|
+
|
|
35
|
+
| Properties | Type | Description |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| deliveryFromTheStore | `string` | Text for the inactive state label. |
|
|
38
|
+
| deliveryStore | `string` | Label text for selecting a store during the active state. |
|
|
39
|
+
|
|
40
|
+
### Customization
|
|
41
|
+
|
|
42
|
+
The Click & Collect component is fully customizable through the `renderer` prop. You can override any part of the UI while keeping the core functionality.
|
|
43
|
+
|
|
44
|
+
#### Renderer Props
|
|
45
|
+
|
|
46
|
+
The `renderer` prop accepts an object with the following properties:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
interface ClickCollectRendererProps {
|
|
50
|
+
renderContainer?: (props: {
|
|
51
|
+
children: React.ReactNode,
|
|
52
|
+
isActive: boolean,
|
|
53
|
+
handleActive: () => void,
|
|
54
|
+
handleDeactivate: () => void
|
|
55
|
+
}) => React.ReactNode;
|
|
56
|
+
|
|
57
|
+
renderInactiveState?: (props: {
|
|
58
|
+
translations: ClickCollectTranslationsProps
|
|
59
|
+
}) => React.ReactNode;
|
|
60
|
+
|
|
61
|
+
renderActiveState?: (props: {
|
|
62
|
+
translations: ClickCollectTranslationsProps,
|
|
63
|
+
cities: any[],
|
|
64
|
+
stores: any[],
|
|
65
|
+
selectedCity: any,
|
|
66
|
+
handleCityChange: (e: ChangeEvent<HTMLSelectElement>) => void,
|
|
67
|
+
handleStoreChange: (e: ChangeEvent<HTMLSelectElement>) => void,
|
|
68
|
+
handleDeactivate: () => void
|
|
69
|
+
}) => React.ReactNode;
|
|
70
|
+
|
|
71
|
+
renderCloseButton?: (props: {
|
|
72
|
+
handleDeactivate: () => void
|
|
73
|
+
}) => React.ReactNode;
|
|
74
|
+
|
|
75
|
+
renderLoader?: () => React.ReactNode;
|
|
76
|
+
}
|
|
19
77
|
```
|
|
20
78
|
|
|
79
|
+
### Usage Examples
|
|
80
|
+
|
|
81
|
+
#### Default Usage
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
import { ClickCollect } from '@akinon/pz-click-collect';
|
|
85
|
+
|
|
86
|
+
<PluginModule
|
|
87
|
+
component={Component.ClickCollect}
|
|
88
|
+
props={{
|
|
89
|
+
addressTypeParam: addressType.requestParam,
|
|
90
|
+
translations: {
|
|
91
|
+
deliveryFromTheStore: 'DELIVERY FROM THE STORE',
|
|
92
|
+
deliveryStore: 'Delivery Store'
|
|
93
|
+
}
|
|
94
|
+
}}
|
|
95
|
+
/>;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Custom UI Usage
|
|
99
|
+
|
|
100
|
+
Here's an example of how to customize the component with branded styling:
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
const customRenderer = {
|
|
104
|
+
// Override the container
|
|
105
|
+
renderContainer: ({ children, isActive, handleActive }) => (
|
|
106
|
+
<div
|
|
107
|
+
role={!isActive ? 'button' : 'div'}
|
|
108
|
+
onClick={() => {
|
|
109
|
+
!isActive && handleActive();
|
|
110
|
+
}}
|
|
111
|
+
className={`
|
|
112
|
+
relative w-full min-h-[8rem] rounded-lg
|
|
113
|
+
${
|
|
114
|
+
isActive
|
|
115
|
+
? 'border-2 border-brand-primary bg-brand-primary/5'
|
|
116
|
+
: 'border border-gray-300 hover:border-brand-primary'
|
|
117
|
+
}
|
|
118
|
+
p-6 transition-all duration-300
|
|
119
|
+
`}
|
|
120
|
+
>
|
|
121
|
+
{children}
|
|
122
|
+
</div>
|
|
123
|
+
),
|
|
124
|
+
|
|
125
|
+
// Override the inactive state display
|
|
126
|
+
renderInactiveState: ({ translations }) => (
|
|
127
|
+
<div className="text-sm flex flex-col justify-center items-center h-full gap-y-3 text-brand-primary">
|
|
128
|
+
<svg
|
|
129
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
130
|
+
width="36"
|
|
131
|
+
height="36"
|
|
132
|
+
viewBox="0 0 24 24"
|
|
133
|
+
fill="none"
|
|
134
|
+
stroke="currentColor"
|
|
135
|
+
strokeWidth="2"
|
|
136
|
+
strokeLinecap="round"
|
|
137
|
+
strokeLinejoin="round"
|
|
138
|
+
>
|
|
139
|
+
<path d="M3 9h18v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9Z" />
|
|
140
|
+
<path d="M3 9V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v4" />
|
|
141
|
+
<path d="M9 13v5" />
|
|
142
|
+
<path d="M15 13v5" />
|
|
143
|
+
</svg>
|
|
144
|
+
<span className="font-medium tracking-wide">
|
|
145
|
+
{translations.deliveryFromTheStore}
|
|
146
|
+
</span>
|
|
147
|
+
</div>
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
// Custom styling for other parts...
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
<PluginModule
|
|
154
|
+
component={Component.ClickCollect}
|
|
155
|
+
props={{
|
|
156
|
+
addressTypeParam: 'shippingAddressPk',
|
|
157
|
+
translations: {
|
|
158
|
+
deliveryFromTheStore: 'Pick Up In-Store',
|
|
159
|
+
deliveryStore: 'Choose a Store'
|
|
160
|
+
},
|
|
161
|
+
renderer: customRenderer
|
|
162
|
+
}}
|
|
163
|
+
/>;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### Partial Customization
|
|
167
|
+
|
|
168
|
+
You can override only specific parts of the UI while keeping the default styling for the rest:
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
<PluginModule
|
|
172
|
+
component={Component.ClickCollect}
|
|
173
|
+
props={{
|
|
174
|
+
addressTypeParam: "shippingAddressPk",
|
|
175
|
+
translations: {
|
|
176
|
+
deliveryFromTheStore: 'Pick Up In-Store',
|
|
177
|
+
deliveryStore: 'Choose a Store'
|
|
178
|
+
},
|
|
179
|
+
renderer={{
|
|
180
|
+
// Override only the active state
|
|
181
|
+
renderActiveState: ({
|
|
182
|
+
translations,
|
|
183
|
+
cities,
|
|
184
|
+
stores,
|
|
185
|
+
handleCityChange,
|
|
186
|
+
handleStoreChange
|
|
187
|
+
}) => (
|
|
188
|
+
<div className="custom-active-state">
|
|
189
|
+
{/* Your custom UI for the active state */}
|
|
190
|
+
</div>
|
|
191
|
+
)
|
|
192
|
+
}}
|
|
193
|
+
}}
|
|
194
|
+
/>
|
|
21
195
|
```
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-click-collect",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"main": "./src/index.tsx",
|
|
5
5
|
"module": "./src/index.tsx",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@types/react": "^
|
|
9
|
-
"@types/react-dom": "^
|
|
10
|
-
"react": "
|
|
11
|
-
"react-dom": "
|
|
12
|
-
"typescript": "^
|
|
8
|
+
"@types/react": "^18.0.15",
|
|
9
|
+
"@types/react-dom": "^18.0.6",
|
|
10
|
+
"react": "19.2.5",
|
|
11
|
+
"react-dom": "19.2.5",
|
|
12
|
+
"typescript": "^4.7.4"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"react": "^19.0.0",
|
|
16
|
-
"react-dom": "^19.0.0"
|
|
15
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
16
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
17
17
|
}
|
|
18
18
|
}
|
package/src/index.tsx
CHANGED
|
@@ -18,22 +18,153 @@ import {
|
|
|
18
18
|
|
|
19
19
|
import { RootState } from 'redux/store';
|
|
20
20
|
|
|
21
|
-
interface ClickCollectTranslationsProps {
|
|
21
|
+
export interface ClickCollectTranslationsProps {
|
|
22
22
|
deliveryFromTheStore: string;
|
|
23
23
|
deliveryStore: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface ClickCollectRendererProps {
|
|
27
|
+
renderContainer?: (props: {
|
|
28
|
+
children: React.ReactNode;
|
|
29
|
+
isActive: boolean;
|
|
30
|
+
handleActive: () => void;
|
|
31
|
+
handleDeactivate: () => void;
|
|
32
|
+
}) => React.ReactNode;
|
|
33
|
+
renderInactiveState?: (props: {
|
|
34
|
+
translations: ClickCollectTranslationsProps;
|
|
35
|
+
}) => React.ReactNode;
|
|
36
|
+
renderActiveState?: (props: {
|
|
37
|
+
translations: ClickCollectTranslationsProps;
|
|
38
|
+
cities: any[];
|
|
39
|
+
stores: any[];
|
|
40
|
+
selectedCity: any;
|
|
41
|
+
handleCityChange: (e: ChangeEvent<HTMLSelectElement>) => void;
|
|
42
|
+
handleStoreChange: (e: ChangeEvent<HTMLSelectElement>) => void;
|
|
43
|
+
handleDeactivate: () => void;
|
|
44
|
+
}) => React.ReactNode;
|
|
45
|
+
renderCloseButton?: (props: {
|
|
46
|
+
handleDeactivate: () => void;
|
|
47
|
+
}) => React.ReactNode;
|
|
48
|
+
renderLoader?: () => React.ReactNode;
|
|
49
|
+
}
|
|
50
|
+
|
|
26
51
|
const defaultTranslations = {
|
|
27
52
|
deliveryFromTheStore: 'DELIVERY FROM THE STORE',
|
|
28
53
|
deliveryStore: 'Delivery Store'
|
|
29
54
|
};
|
|
30
55
|
|
|
56
|
+
const DefaultContainer = ({
|
|
57
|
+
children,
|
|
58
|
+
isActive,
|
|
59
|
+
handleActive
|
|
60
|
+
}: {
|
|
61
|
+
children: React.ReactNode;
|
|
62
|
+
isActive: boolean;
|
|
63
|
+
handleActive: () => void;
|
|
64
|
+
}) => (
|
|
65
|
+
<div
|
|
66
|
+
role={!isActive ? 'button' : 'div'}
|
|
67
|
+
onClick={() => {
|
|
68
|
+
!isActive && handleActive();
|
|
69
|
+
}}
|
|
70
|
+
className={clsx(
|
|
71
|
+
'relative w-full min-h-[8rem] border shadow p-4',
|
|
72
|
+
"hover:after:content-[''] hover:after:border-4 hover:after:opacity-30 hover:after:transition-opacity",
|
|
73
|
+
'after:border-secondary-400 after:absolute after:inset-0 after:opacity-0 after:duration-150 after:-z-10'
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
{children}
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const DefaultInactiveState = ({
|
|
81
|
+
translations
|
|
82
|
+
}: {
|
|
83
|
+
translations: ClickCollectTranslationsProps;
|
|
84
|
+
}) => (
|
|
85
|
+
<div className="text-xs text-center flex justify-center items-center h-full gap-x-2">
|
|
86
|
+
<Icon name="plus" size={12} />
|
|
87
|
+
<span data-testid="click-collect-add-new-address">
|
|
88
|
+
{translations.deliveryFromTheStore}
|
|
89
|
+
</span>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const DefaultActiveState = ({
|
|
94
|
+
translations,
|
|
95
|
+
cities,
|
|
96
|
+
stores,
|
|
97
|
+
handleCityChange,
|
|
98
|
+
handleStoreChange
|
|
99
|
+
}: {
|
|
100
|
+
translations: ClickCollectTranslationsProps;
|
|
101
|
+
cities: any[];
|
|
102
|
+
stores: any[];
|
|
103
|
+
selectedCity: any;
|
|
104
|
+
handleCityChange: (e: ChangeEvent<HTMLSelectElement>) => void;
|
|
105
|
+
handleStoreChange: (e: ChangeEvent<HTMLSelectElement>) => void;
|
|
106
|
+
handleDeactivate: () => void;
|
|
107
|
+
}) => (
|
|
108
|
+
<div className="relative w-full">
|
|
109
|
+
<label
|
|
110
|
+
htmlFor="cities"
|
|
111
|
+
className="block mb-2 text-sm text-center font-light text-black-900"
|
|
112
|
+
>
|
|
113
|
+
{translations.deliveryStore}
|
|
114
|
+
</label>
|
|
115
|
+
<select
|
|
116
|
+
id="cities"
|
|
117
|
+
className="bg-white border border-gray-300 font-light text-black-900 text-sm block w-full p-1 mb-2 focus:ring-black-500 focus:border-black-500"
|
|
118
|
+
onChange={handleCityChange}
|
|
119
|
+
>
|
|
120
|
+
{cities.map((city) => (
|
|
121
|
+
<option key={city.pk} value={city.pk}>
|
|
122
|
+
{city.name}
|
|
123
|
+
</option>
|
|
124
|
+
))}
|
|
125
|
+
</select>
|
|
126
|
+
<select
|
|
127
|
+
id="stores"
|
|
128
|
+
onChange={handleStoreChange}
|
|
129
|
+
className="bg-white border border-gray-300 font-light text-black-900 text-sm block w-full p-1 mb-2 focus:ring-black-500 focus:border-black-500"
|
|
130
|
+
>
|
|
131
|
+
{stores.map((store) => (
|
|
132
|
+
<option key={store.pk} value={store.pk}>
|
|
133
|
+
{store.name}
|
|
134
|
+
</option>
|
|
135
|
+
))}
|
|
136
|
+
</select>
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const DefaultCloseButton = ({
|
|
141
|
+
handleDeactivate
|
|
142
|
+
}: {
|
|
143
|
+
handleDeactivate: () => void;
|
|
144
|
+
}) => (
|
|
145
|
+
<div
|
|
146
|
+
role="button"
|
|
147
|
+
onClick={handleDeactivate}
|
|
148
|
+
className="absolute cursor-pointer top-2 right-2 hover:bg-byarlack-100/[.1] p-2 z-10 rounded-full"
|
|
149
|
+
>
|
|
150
|
+
<Icon name="close" size={9} />
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const DefaultLoader = () => (
|
|
155
|
+
<div className="absolute top-0 left-0 w-full h-full bg-white/[.9] z-10">
|
|
156
|
+
<LoaderSpinner />
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
|
|
31
160
|
export function ClickCollect({
|
|
32
161
|
addressTypeParam,
|
|
33
|
-
translations
|
|
162
|
+
translations,
|
|
163
|
+
renderer = {}
|
|
34
164
|
}: {
|
|
35
165
|
addressTypeParam: string;
|
|
36
166
|
translations: ClickCollectTranslationsProps;
|
|
167
|
+
renderer?: ClickCollectRendererProps;
|
|
37
168
|
}) {
|
|
38
169
|
const _translations = {
|
|
39
170
|
...defaultTranslations,
|
|
@@ -82,7 +213,7 @@ export function ClickCollect({
|
|
|
82
213
|
|
|
83
214
|
const defaultDeliveryOption = useMemo(
|
|
84
215
|
() =>
|
|
85
|
-
deliveryOptions
|
|
216
|
+
deliveryOptions?.find(
|
|
86
217
|
(option) => option?.delivery_option_type === 'customer'
|
|
87
218
|
),
|
|
88
219
|
[deliveryOptions]
|
|
@@ -90,7 +221,7 @@ export function ClickCollect({
|
|
|
90
221
|
|
|
91
222
|
const retailStoreDeliveryOption = useMemo(
|
|
92
223
|
() =>
|
|
93
|
-
deliveryOptions
|
|
224
|
+
deliveryOptions?.find(
|
|
94
225
|
(option) => option?.delivery_option_type === 'retail_store'
|
|
95
226
|
),
|
|
96
227
|
[deliveryOptions]
|
|
@@ -240,73 +371,36 @@ export function ClickCollect({
|
|
|
240
371
|
|
|
241
372
|
if (addressTypeParam !== 'shippingAddressPk') return;
|
|
242
373
|
|
|
374
|
+
const RenderContainer = renderer.renderContainer || DefaultContainer;
|
|
375
|
+
const RenderInactiveState =
|
|
376
|
+
renderer.renderInactiveState || DefaultInactiveState;
|
|
377
|
+
const RenderActiveState = renderer.renderActiveState || DefaultActiveState;
|
|
378
|
+
const RenderCloseButton = renderer.renderCloseButton || DefaultCloseButton;
|
|
379
|
+
const RenderLoader = renderer.renderLoader || DefaultLoader;
|
|
380
|
+
|
|
243
381
|
return (
|
|
244
|
-
<
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}}
|
|
249
|
-
className={clsx(
|
|
250
|
-
'relative w-full min-h-[8rem] border border-gray-200 shadow-sm p-4',
|
|
251
|
-
"hover:after:content-[''] hover:after:border-4 hover:after:opacity-30 hover:after:transition-opacity",
|
|
252
|
-
'after:border-secondary-400 after:absolute after:inset-0 after:opacity-0 after:duration-150 after:-z-10'
|
|
253
|
-
)}
|
|
382
|
+
<RenderContainer
|
|
383
|
+
isActive={isActive}
|
|
384
|
+
handleActive={handleActive}
|
|
385
|
+
handleDeactivate={handleDeactivate}
|
|
254
386
|
>
|
|
255
387
|
<div className="text-xs flex justify-center items-center h-full gap-x-2">
|
|
256
|
-
{isActive &&
|
|
257
|
-
|
|
258
|
-
role="button"
|
|
259
|
-
onClick={handleDeactivate}
|
|
260
|
-
className="absolute cursor-pointer top-2 right-2 hover:bg-byarlack-100/[.1] p-2 z-10 rounded-full "
|
|
261
|
-
>
|
|
262
|
-
<Icon name="close" size={9} />
|
|
263
|
-
</div>
|
|
264
|
-
)}
|
|
265
|
-
{loading && (
|
|
266
|
-
<div className="absolute top-0 left-0 w-full h-full bg-white/[.9] z-10">
|
|
267
|
-
<LoaderSpinner />
|
|
268
|
-
</div>
|
|
269
|
-
)}
|
|
388
|
+
{isActive && <RenderCloseButton handleDeactivate={handleDeactivate} />}
|
|
389
|
+
{loading && <RenderLoader />}
|
|
270
390
|
{!isActive ? (
|
|
271
|
-
<
|
|
272
|
-
<Icon name="plus" size={12} />
|
|
273
|
-
<span data-testid="click-collect-add-new-address">
|
|
274
|
-
{_translations.deliveryFromTheStore}
|
|
275
|
-
</span>
|
|
276
|
-
</div>
|
|
391
|
+
<RenderInactiveState translations={_translations} />
|
|
277
392
|
) : (
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
className="bg-white border border-gray-300 font-light text-black-900 text-sm block w-full p-1 mb-2 focus:ring-black-500 focus:border-black-500"
|
|
288
|
-
onChange={handleCityChange}
|
|
289
|
-
>
|
|
290
|
-
{getUniqueCities.map((city) => (
|
|
291
|
-
<option key={city.pk} value={city.pk}>
|
|
292
|
-
{city.name}
|
|
293
|
-
</option>
|
|
294
|
-
))}
|
|
295
|
-
</select>
|
|
296
|
-
<select
|
|
297
|
-
id="stores"
|
|
298
|
-
onChange={handleStoreChange}
|
|
299
|
-
className="bg-white border border-gray-300 font-light text-black-900 text-sm block w-full p-1 mb-2 focus:ring-black-500 focus:border-black-500"
|
|
300
|
-
>
|
|
301
|
-
{retailStoresForCity.map((store) => (
|
|
302
|
-
<option key={store.pk} value={store.pk}>
|
|
303
|
-
{store.name}
|
|
304
|
-
</option>
|
|
305
|
-
))}
|
|
306
|
-
</select>
|
|
307
|
-
</div>
|
|
393
|
+
<RenderActiveState
|
|
394
|
+
translations={_translations}
|
|
395
|
+
cities={getUniqueCities}
|
|
396
|
+
stores={retailStoresForCity}
|
|
397
|
+
selectedCity={selectedCity}
|
|
398
|
+
handleCityChange={handleCityChange}
|
|
399
|
+
handleStoreChange={handleStoreChange}
|
|
400
|
+
handleDeactivate={handleDeactivate}
|
|
401
|
+
/>
|
|
308
402
|
)}
|
|
309
403
|
</div>
|
|
310
|
-
</
|
|
404
|
+
</RenderContainer>
|
|
311
405
|
);
|
|
312
406
|
}
|