@akinon/pz-basket-gift-pack 2.0.0-beta.2 → 2.0.0-beta.21
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 +122 -6
- package/README.md +144 -4
- package/package.json +9 -9
- package/src/index.tsx +183 -159
package/CHANGELOG.md
CHANGED
|
@@ -1,18 +1,134 @@
|
|
|
1
1
|
# @akinon/pz-basket-gift-pack
|
|
2
2
|
|
|
3
|
-
## 2.0.0-beta.
|
|
3
|
+
## 2.0.0-beta.21
|
|
4
4
|
|
|
5
|
-
## 2.0.0-beta.
|
|
5
|
+
## 2.0.0-beta.20
|
|
6
|
+
|
|
7
|
+
## 1.126.0
|
|
8
|
+
|
|
9
|
+
## 1.125.2
|
|
10
|
+
|
|
11
|
+
## 1.125.1
|
|
12
|
+
|
|
13
|
+
## 1.125.0
|
|
14
|
+
|
|
15
|
+
## 1.124.0
|
|
16
|
+
|
|
17
|
+
## 1.123.0
|
|
18
|
+
|
|
19
|
+
## 1.122.0
|
|
20
|
+
|
|
21
|
+
## 1.121.0
|
|
22
|
+
|
|
23
|
+
## 1.120.0
|
|
24
|
+
|
|
25
|
+
## 1.119.0
|
|
26
|
+
|
|
27
|
+
## 1.118.0
|
|
28
|
+
|
|
29
|
+
## 1.117.0
|
|
30
|
+
|
|
31
|
+
## 1.116.0
|
|
32
|
+
|
|
33
|
+
## 1.115.0
|
|
34
|
+
|
|
35
|
+
## 1.114.0
|
|
36
|
+
|
|
37
|
+
## 1.113.0
|
|
38
|
+
|
|
39
|
+
## 1.112.0
|
|
40
|
+
|
|
41
|
+
## 1.111.0
|
|
42
|
+
|
|
43
|
+
## 1.110.0
|
|
44
|
+
|
|
45
|
+
## 1.109.0
|
|
46
|
+
|
|
47
|
+
## 1.108.0
|
|
48
|
+
|
|
49
|
+
## 1.107.0
|
|
50
|
+
|
|
51
|
+
### Minor Changes
|
|
52
|
+
|
|
53
|
+
- 72bfcbf2: ZERO-3347: Manage save button disable status
|
|
54
|
+
|
|
55
|
+
## 1.106.0
|
|
56
|
+
|
|
57
|
+
## 1.105.0
|
|
58
|
+
|
|
59
|
+
## 1.104.0
|
|
60
|
+
|
|
61
|
+
### Minor Changes
|
|
62
|
+
|
|
63
|
+
- 2ba89b3: ZERO-3361: Refactor basket gift pack component
|
|
64
|
+
|
|
65
|
+
## 1.103.0
|
|
66
|
+
|
|
67
|
+
## 1.102.0
|
|
68
|
+
|
|
69
|
+
## 1.101.0
|
|
70
|
+
|
|
71
|
+
## 1.100.0
|
|
72
|
+
|
|
73
|
+
## 1.99.0
|
|
6
74
|
|
|
7
75
|
### Minor Changes
|
|
8
76
|
|
|
9
|
-
- ZERO-
|
|
77
|
+
- d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
|
|
78
|
+
|
|
79
|
+
## 1.98.0
|
|
80
|
+
|
|
81
|
+
## 1.97.0
|
|
82
|
+
|
|
83
|
+
## 1.96.0
|
|
84
|
+
|
|
85
|
+
## 1.95.0
|
|
86
|
+
|
|
87
|
+
## 1.94.0
|
|
88
|
+
|
|
89
|
+
## 1.93.0
|
|
90
|
+
|
|
91
|
+
## 1.92.0
|
|
92
|
+
|
|
93
|
+
## 1.91.0
|
|
94
|
+
|
|
95
|
+
## 1.90.0
|
|
96
|
+
|
|
97
|
+
## 1.89.0
|
|
98
|
+
|
|
99
|
+
## 1.88.0
|
|
100
|
+
|
|
101
|
+
### Minor Changes
|
|
102
|
+
|
|
103
|
+
- 3037704: ZERO-3328: Add data-testid attributes for improved testing in BasketItem and BasketGiftPack components
|
|
104
|
+
|
|
105
|
+
## 1.87.0
|
|
106
|
+
|
|
107
|
+
## 1.86.0
|
|
108
|
+
|
|
109
|
+
## 1.85.0
|
|
110
|
+
|
|
111
|
+
## 1.84.0
|
|
112
|
+
|
|
113
|
+
### Minor Changes
|
|
114
|
+
|
|
115
|
+
- 624a4eb: ZERO-3276: Update installation instructions across multiple README files to standardize format and improve clarity
|
|
116
|
+
|
|
117
|
+
## 1.83.0
|
|
118
|
+
|
|
119
|
+
## 1.82.0
|
|
120
|
+
|
|
121
|
+
## 1.81.0
|
|
122
|
+
|
|
123
|
+
## 1.80.0
|
|
124
|
+
|
|
125
|
+
## 1.79.0
|
|
10
126
|
|
|
11
|
-
##
|
|
127
|
+
## 1.78.0
|
|
12
128
|
|
|
13
|
-
|
|
129
|
+
## 1.77.0
|
|
14
130
|
|
|
15
|
-
|
|
131
|
+
## 1.76.0
|
|
16
132
|
|
|
17
133
|
## 1.75.0
|
|
18
134
|
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @akinon/pz-basket-gift-pack
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Installation method
|
|
4
|
+
|
|
5
|
+
You can use the following command to install the extension with the latest plugins:
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
|
-
# For latest version
|
|
7
|
-
yarn add @akinon/pz-basket-gift-pack
|
|
8
8
|
|
|
9
|
-
# Preferred installation method
|
|
10
9
|
npx @akinon/projectzero@latest --plugins
|
|
10
|
+
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
### Props
|
|
@@ -19,3 +19,143 @@ npx @akinon/projectzero@latest --plugins
|
|
|
19
19
|
| modalClassName | `string` | This prop is used to customize the overall style of the modal. |
|
|
20
20
|
| modalTitle | `string` | This prop sets the title of the modal. |
|
|
21
21
|
| modalContentClassName | `string` | This prop is used to customize the style of the modal content. |
|
|
22
|
+
| customUIRender | `React.ReactNode` | Optional function to fully customize the gift pack rendering. Receives hasGiftPack, hasNote, note, textAreaCount, onAddGiftPack, onRemoveGiftPack, onAddNote, onRemoveNote, formContent and translations props. |
|
|
23
|
+
| customGiftNoteFormUIRender | `React.ReactNode` | Optional function to fully customize the form rendering. Receives register, errors, note, textAreaCount, onSubmit, removeNote and handleSubmit props. |
|
|
24
|
+
|
|
25
|
+
### Customizing Gift Pack
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
29
|
+
|
|
30
|
+
<PluginModule
|
|
31
|
+
component={Component.BasketGiftPack}
|
|
32
|
+
props={{
|
|
33
|
+
basketItem,
|
|
34
|
+
customUIRender: ({
|
|
35
|
+
hasGiftPack,
|
|
36
|
+
hasNote,
|
|
37
|
+
onAddGiftPack,
|
|
38
|
+
onRemoveGiftPack,
|
|
39
|
+
onAddNote,
|
|
40
|
+
formContent,
|
|
41
|
+
translations
|
|
42
|
+
}) => (
|
|
43
|
+
<>
|
|
44
|
+
<div className="flex gap-4">
|
|
45
|
+
<div className="flex items-center gap-2">
|
|
46
|
+
<Icon
|
|
47
|
+
name="giftbox"
|
|
48
|
+
size={15}
|
|
49
|
+
className={clsx(
|
|
50
|
+
hasGiftPack ? 'text-[#e85150]' : 'text-[#000000]'
|
|
51
|
+
)}
|
|
52
|
+
/>
|
|
53
|
+
{hasGiftPack ? (
|
|
54
|
+
<span className="text-[0.75rem]">
|
|
55
|
+
{translations.giftPackAdded}
|
|
56
|
+
</span>
|
|
57
|
+
) : (
|
|
58
|
+
<Button
|
|
59
|
+
appearance="ghost"
|
|
60
|
+
className="text-[#000000] cursor-pointer underline border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]"
|
|
61
|
+
onClick={onAddGiftPack}
|
|
62
|
+
data-testid="add-basket-gift-pack"
|
|
63
|
+
>
|
|
64
|
+
{translations.addGiftPack}
|
|
65
|
+
</Button>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
{hasGiftPack && (
|
|
70
|
+
<>
|
|
71
|
+
<Button
|
|
72
|
+
appearance="ghost"
|
|
73
|
+
className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
|
|
74
|
+
onClick={onAddNote}
|
|
75
|
+
data-testid="add-basket-gift-pack-note"
|
|
76
|
+
>
|
|
77
|
+
{hasNote.title}
|
|
78
|
+
</Button>
|
|
79
|
+
<Button
|
|
80
|
+
appearance="ghost"
|
|
81
|
+
className={clsx(
|
|
82
|
+
'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
|
|
83
|
+
{
|
|
84
|
+
hidden: !hasGiftPack
|
|
85
|
+
}
|
|
86
|
+
)}
|
|
87
|
+
onClick={onRemoveGiftPack}
|
|
88
|
+
data-testid="remove-basket-gift-pack"
|
|
89
|
+
>
|
|
90
|
+
{translations.removeGiftPack}
|
|
91
|
+
</Button>
|
|
92
|
+
</>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div className="w-full">
|
|
97
|
+
{hasNote.state ? <div className="mt-4">{formContent}</div> : null}
|
|
98
|
+
</div>
|
|
99
|
+
</>
|
|
100
|
+
)
|
|
101
|
+
}}
|
|
102
|
+
/>;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Customizing Gift Note Form
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
109
|
+
|
|
110
|
+
<PluginModule
|
|
111
|
+
component={Component.BasketGiftPack}
|
|
112
|
+
props={{
|
|
113
|
+
basketItem,
|
|
114
|
+
customGiftNoteFormUIRender: ({
|
|
115
|
+
register,
|
|
116
|
+
errors,
|
|
117
|
+
note,
|
|
118
|
+
textAreaCount,
|
|
119
|
+
onSubmit,
|
|
120
|
+
removeNote,
|
|
121
|
+
handleSubmit
|
|
122
|
+
}) => (
|
|
123
|
+
<div className="bg-gray-100 p-4 rounded-md shadow-lg">
|
|
124
|
+
<h4 className="text-lg font-semibold mb-2">🎁 Add Your Note</h4>
|
|
125
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
126
|
+
<textarea
|
|
127
|
+
className="w-full border border-gray-300 p-2"
|
|
128
|
+
{...register('message')}
|
|
129
|
+
placeholder="Mesajını yaz..."
|
|
130
|
+
rows={5}
|
|
131
|
+
value={note}
|
|
132
|
+
/>
|
|
133
|
+
{errors.message && (
|
|
134
|
+
<p className="text-red-500 text-sm">{errors.message.message}</p>
|
|
135
|
+
)}
|
|
136
|
+
<div className="flex justify-between items-center mt-2">
|
|
137
|
+
<span className="text-sm text-gray-500">
|
|
138
|
+
{textAreaCount}/ 160 characters
|
|
139
|
+
</span>
|
|
140
|
+
<div className="flex gap-2">
|
|
141
|
+
<button
|
|
142
|
+
type="button"
|
|
143
|
+
onClick={removeNote}
|
|
144
|
+
className="text-sm underline"
|
|
145
|
+
>
|
|
146
|
+
Delete Note
|
|
147
|
+
</button>
|
|
148
|
+
<button
|
|
149
|
+
type="submit"
|
|
150
|
+
className="bg-black text-white px-3 py-1 text-sm rounded"
|
|
151
|
+
>
|
|
152
|
+
Save
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</form>
|
|
157
|
+
</div>
|
|
158
|
+
)
|
|
159
|
+
}}
|
|
160
|
+
/>;
|
|
161
|
+
```
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-basket-gift-pack",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.21",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"react": "^19.0.0",
|
|
8
|
-
"react-dom": "^19.0.0"
|
|
7
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
8
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@types/node": "^
|
|
12
|
-
"@types/react": "^
|
|
13
|
-
"@types/react-dom": "^
|
|
14
|
-
"react": "
|
|
15
|
-
"react-dom": "
|
|
16
|
-
"typescript": "^
|
|
11
|
+
"@types/node": "^18.7.8",
|
|
12
|
+
"@types/react": "^18.0.17",
|
|
13
|
+
"@types/react-dom": "^18.0.6",
|
|
14
|
+
"react": "19.2.5",
|
|
15
|
+
"react-dom": "19.2.5",
|
|
16
|
+
"typescript": "^4.7.4"
|
|
17
17
|
}
|
|
18
18
|
}
|
package/src/index.tsx
CHANGED
|
@@ -4,38 +4,69 @@ import {
|
|
|
4
4
|
} from './endpoints';
|
|
5
5
|
import clsx from 'clsx';
|
|
6
6
|
import { twMerge } from 'tailwind-merge';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
useForm,
|
|
9
|
+
SubmitHandler,
|
|
10
|
+
UseFormRegister,
|
|
11
|
+
FieldErrors,
|
|
12
|
+
UseFormHandleSubmit
|
|
13
|
+
} from 'react-hook-form';
|
|
8
14
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
9
15
|
import * as yup from 'yup';
|
|
10
16
|
import { useEffect, useState } from 'react';
|
|
11
17
|
import { Button, Icon, Modal } from '@akinon/next/components';
|
|
12
18
|
import { BasketItem as BasketItemType } from '@akinon/next/types';
|
|
13
19
|
|
|
20
|
+
const defaultTranslations = {
|
|
21
|
+
placeholderInput:
|
|
22
|
+
'You can leave this area empty. However it will be a gift package without note.',
|
|
23
|
+
warningMessage: 'Ensure this field has no more than 160 characters.',
|
|
24
|
+
addNote: 'Add Note',
|
|
25
|
+
addGiftNote: 'Add Gift Note',
|
|
26
|
+
changeNote: 'Change Note',
|
|
27
|
+
giftPackAdded: 'Gift Pack Added',
|
|
28
|
+
addGiftPack: 'Add Gift Pack',
|
|
29
|
+
removeGiftPack: 'Remove Gift Pack',
|
|
30
|
+
charactersLength: 'characters left',
|
|
31
|
+
removeNote: 'Remove Note',
|
|
32
|
+
save: 'SAVE',
|
|
33
|
+
saving: 'SAVING...',
|
|
34
|
+
close: 'Close'
|
|
35
|
+
};
|
|
36
|
+
|
|
14
37
|
interface GiftPackForm {
|
|
15
38
|
message: string;
|
|
16
39
|
}
|
|
17
|
-
|
|
40
|
+
interface CustomRenderParams {
|
|
41
|
+
hasGiftPack: boolean;
|
|
42
|
+
hasNote: { title: string; state: boolean };
|
|
43
|
+
note: string;
|
|
44
|
+
textAreaCount: number;
|
|
45
|
+
onAddGiftPack: () => void;
|
|
46
|
+
onRemoveGiftPack: () => void;
|
|
47
|
+
onAddNote: () => void;
|
|
48
|
+
onRemoveNote: () => void;
|
|
49
|
+
formContent: React.ReactNode;
|
|
50
|
+
translations: typeof defaultTranslations;
|
|
51
|
+
}
|
|
18
52
|
interface Props {
|
|
19
53
|
basketItem: BasketItemType;
|
|
20
54
|
useModal?: boolean;
|
|
21
55
|
modalTitle?: string;
|
|
22
56
|
modalClassName?: string;
|
|
23
57
|
modalContentClassName?: string;
|
|
24
|
-
translations?:
|
|
25
|
-
placeholderInput?: string;
|
|
26
|
-
warningMessage?: string;
|
|
27
|
-
addNote?: string;
|
|
28
|
-
addGiftNote?: string;
|
|
29
|
-
changeNote?: string;
|
|
30
|
-
giftPackAdded?: string;
|
|
31
|
-
addGiftPack?: string;
|
|
32
|
-
removeGiftPack?: string;
|
|
33
|
-
charactersLength?: string;
|
|
34
|
-
removeNote?: string;
|
|
35
|
-
save?: string;
|
|
36
|
-
close?: string;
|
|
37
|
-
};
|
|
58
|
+
translations?: Partial<typeof defaultTranslations>;
|
|
38
59
|
className?: string;
|
|
60
|
+
customUIRender?: (params: CustomRenderParams) => React.ReactNode;
|
|
61
|
+
customGiftNoteFormUIRender?: (params: {
|
|
62
|
+
register: UseFormRegister<GiftPackForm>;
|
|
63
|
+
errors: FieldErrors<GiftPackForm>;
|
|
64
|
+
note: string;
|
|
65
|
+
textAreaCount: number;
|
|
66
|
+
onSubmit: () => void;
|
|
67
|
+
removeNote: () => void;
|
|
68
|
+
handleSubmit: UseFormHandleSubmit<GiftPackForm>;
|
|
69
|
+
}) => React.ReactNode;
|
|
39
70
|
}
|
|
40
71
|
|
|
41
72
|
export const BasketGiftPack = ({
|
|
@@ -45,30 +76,13 @@ export const BasketGiftPack = ({
|
|
|
45
76
|
useModal = false,
|
|
46
77
|
modalTitle = 'Gift Note',
|
|
47
78
|
modalClassName,
|
|
48
|
-
modalContentClassName
|
|
79
|
+
modalContentClassName,
|
|
80
|
+
customUIRender,
|
|
81
|
+
customGiftNoteFormUIRender
|
|
49
82
|
}: Props) => {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
warningMessage: 'Ensure this field has no more than 160 characters.',
|
|
54
|
-
addNote: 'Add Note',
|
|
55
|
-
addGiftNote: 'Add Gift Note',
|
|
56
|
-
changeNote: 'Change Note',
|
|
57
|
-
giftPackAdded: 'Gift Pack Added',
|
|
58
|
-
addGiftPack: 'Add Gift Pack',
|
|
59
|
-
removeGiftPack: 'Remove Gift Pack',
|
|
60
|
-
charactersLength: 'characters left',
|
|
61
|
-
removeNote: 'Remove Note',
|
|
62
|
-
save: 'SAVE',
|
|
63
|
-
close: 'Close'
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const _translations = {
|
|
67
|
-
...defaultTranslations,
|
|
68
|
-
...translations
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const [addGiftPackage] = useAddGiftPackageMutation();
|
|
83
|
+
const _translations = { ...defaultTranslations, ...translations };
|
|
84
|
+
const [addGiftPackage, { isLoading: isAddingGiftPackage }] =
|
|
85
|
+
useAddGiftPackageMutation();
|
|
72
86
|
const [removeGiftPackage] = useRemoveGiftPackageMutation();
|
|
73
87
|
const [hasGiftPack, setHasGiftPack] = useState(false);
|
|
74
88
|
const [hasNote, setHasNote] = useState({
|
|
@@ -79,10 +93,9 @@ export const BasketGiftPack = ({
|
|
|
79
93
|
const [note, setNote] = useState('');
|
|
80
94
|
const defaultMessage = 'NO-GIFT-NOTE';
|
|
81
95
|
|
|
82
|
-
const
|
|
83
|
-
yup.
|
|
84
|
-
|
|
85
|
-
});
|
|
96
|
+
const schema = yup.object().shape({
|
|
97
|
+
message: yup.string().max(160, _translations.warningMessage)
|
|
98
|
+
});
|
|
86
99
|
|
|
87
100
|
const {
|
|
88
101
|
register,
|
|
@@ -90,54 +103,83 @@ export const BasketGiftPack = ({
|
|
|
90
103
|
handleSubmit,
|
|
91
104
|
formState: { errors }
|
|
92
105
|
} = useForm<GiftPackForm>({
|
|
93
|
-
resolver: yupResolver(
|
|
106
|
+
resolver: yupResolver(schema) as any
|
|
94
107
|
});
|
|
95
108
|
|
|
96
109
|
const onSubmit: SubmitHandler<GiftPackForm> = async (data) => {
|
|
97
|
-
addGiftPackage({ id: basketItem.id, message: data.message })
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
setHasNote((prevstate) => ({ ...prevstate, state: false }));
|
|
101
|
-
changeNoteTitle(data.message);
|
|
102
|
-
});
|
|
110
|
+
await addGiftPackage({ id: basketItem.id, message: data.message }).unwrap();
|
|
111
|
+
setHasNote({ ...hasNote, state: false });
|
|
112
|
+
changeNoteTitle(data.message);
|
|
103
113
|
};
|
|
104
114
|
|
|
105
|
-
const addGiftPack = () => {
|
|
106
|
-
addGiftPackage({
|
|
107
|
-
.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
const addGiftPack = async () => {
|
|
116
|
+
await addGiftPackage({
|
|
117
|
+
id: basketItem.id,
|
|
118
|
+
message: defaultMessage
|
|
119
|
+
}).unwrap();
|
|
120
|
+
setHasGiftPack(true);
|
|
121
|
+
setHasNote({ ...hasNote, state: false });
|
|
112
122
|
};
|
|
113
123
|
|
|
114
124
|
const removeGiftPack = () => {
|
|
115
125
|
removeGiftPackage({ id: basketItem.id });
|
|
116
126
|
setHasGiftPack(false);
|
|
117
|
-
setHasNote(
|
|
127
|
+
setHasNote({ ...hasNote, state: false });
|
|
118
128
|
};
|
|
119
129
|
|
|
120
130
|
const removeNote = () => {
|
|
121
131
|
addGiftPackage({ id: basketItem.id, message: defaultMessage });
|
|
122
|
-
setHasNote(
|
|
132
|
+
setHasNote({ ...hasNote, state: false });
|
|
123
133
|
changeNoteTitle(defaultMessage);
|
|
124
134
|
};
|
|
125
135
|
|
|
126
|
-
const changeNoteTitle = (value) => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
} else {
|
|
133
|
-
setHasNote((prevstate) => ({
|
|
134
|
-
...prevstate,
|
|
135
|
-
title: _translations.addNote
|
|
136
|
-
}));
|
|
137
|
-
}
|
|
136
|
+
const changeNoteTitle = (value: string) => {
|
|
137
|
+
const title =
|
|
138
|
+
value !== defaultMessage
|
|
139
|
+
? _translations.changeNote
|
|
140
|
+
: _translations.addNote;
|
|
141
|
+
setHasNote((prev) => ({ ...prev, title }));
|
|
138
142
|
};
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
for (const [key, value] of Object.entries(basketItem.attributes)) {
|
|
146
|
+
if (value === '') {
|
|
147
|
+
setHasGiftPack(false);
|
|
148
|
+
setHasNote({ ...hasNote, state: false });
|
|
149
|
+
setNote('');
|
|
150
|
+
setTextAreaCount(0);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (key) {
|
|
155
|
+
changeNoteTitle(value);
|
|
156
|
+
setNote(value);
|
|
157
|
+
setHasGiftPack(true);
|
|
158
|
+
setTextAreaCount(value === defaultMessage ? 0 : value.length);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}, [basketItem.attributes]);
|
|
162
|
+
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
const subscription = watch(({ message }) => {
|
|
165
|
+
setNote(message);
|
|
166
|
+
setTextAreaCount(message.length);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return () => subscription.unsubscribe();
|
|
170
|
+
}, [watch]);
|
|
171
|
+
|
|
172
|
+
const formContent = customGiftNoteFormUIRender ? (
|
|
173
|
+
customGiftNoteFormUIRender({
|
|
174
|
+
register,
|
|
175
|
+
errors,
|
|
176
|
+
note,
|
|
177
|
+
textAreaCount,
|
|
178
|
+
onSubmit: () => handleSubmit(onSubmit)(),
|
|
179
|
+
removeNote,
|
|
180
|
+
handleSubmit
|
|
181
|
+
})
|
|
182
|
+
) : (
|
|
141
183
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
142
184
|
{!useModal && (
|
|
143
185
|
<div className="flex justify-between mb-3">
|
|
@@ -149,7 +191,7 @@ export const BasketGiftPack = ({
|
|
|
149
191
|
className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
|
|
150
192
|
onClick={(e) => {
|
|
151
193
|
e.preventDefault();
|
|
152
|
-
setHasNote(
|
|
194
|
+
setHasNote({ ...hasNote, state: false });
|
|
153
195
|
}}
|
|
154
196
|
>
|
|
155
197
|
{_translations.close}
|
|
@@ -157,80 +199,55 @@ export const BasketGiftPack = ({
|
|
|
157
199
|
</div>
|
|
158
200
|
)}
|
|
159
201
|
<textarea
|
|
160
|
-
className="w-full border border-
|
|
202
|
+
className="w-full border border-[#4a4f53] p-4 text-[0.75rem] placeholder:text-[#c8c9c8]"
|
|
161
203
|
rows={7}
|
|
162
|
-
name="message"
|
|
163
|
-
value={note !== defaultMessage ? note : ' '}
|
|
164
204
|
placeholder={_translations.placeholderInput}
|
|
165
205
|
{...register('message')}
|
|
206
|
+
value={note !== defaultMessage ? note : ''}
|
|
207
|
+
data-testid="basket-gift-pack-note-input"
|
|
166
208
|
/>
|
|
167
209
|
{errors.message && (
|
|
168
|
-
<span className="text-sm text-[#d72a04]">{errors.message.message}</span>
|
|
210
|
+
<span className="text-sm text-[#d72a04]">{String(errors.message.message)}</span>
|
|
169
211
|
)}
|
|
170
|
-
<div className="flex justify-between items-center
|
|
212
|
+
<div className="flex justify-between mt-2 items-center">
|
|
171
213
|
<span
|
|
172
214
|
className={clsx(
|
|
173
|
-
'text-[0.75rem]
|
|
215
|
+
'text-[0.75rem]',
|
|
174
216
|
textAreaCount > 160 ? 'text-[#e85150]' : 'text-[#82a27c]'
|
|
175
217
|
)}
|
|
176
218
|
>
|
|
177
219
|
{textAreaCount}/160 {_translations.charactersLength}
|
|
178
220
|
</span>
|
|
179
|
-
<div className="flex items-center
|
|
221
|
+
<div className="flex gap-3 items-center">
|
|
180
222
|
<Button
|
|
181
223
|
appearance="ghost"
|
|
182
224
|
className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
|
|
183
225
|
onClick={removeNote}
|
|
226
|
+
data-testid="basket-gift-pack-note-remove-button"
|
|
184
227
|
>
|
|
185
228
|
{_translations.removeNote}
|
|
186
229
|
</Button>
|
|
187
|
-
<Button
|
|
188
|
-
|
|
230
|
+
<Button
|
|
231
|
+
type="submit"
|
|
232
|
+
className="w-28 h-7 font-medium uppercase"
|
|
233
|
+
data-testid="basket-gift-pack-note-save-button"
|
|
234
|
+
disabled={
|
|
235
|
+
isAddingGiftPackage ||
|
|
236
|
+
textAreaCount === 0 ||
|
|
237
|
+
note.trim() === '' ||
|
|
238
|
+
note === defaultMessage
|
|
239
|
+
}
|
|
240
|
+
>
|
|
241
|
+
{isAddingGiftPackage ? _translations.saving : _translations.save}
|
|
189
242
|
</Button>
|
|
190
243
|
</div>
|
|
191
244
|
</div>
|
|
192
245
|
</form>
|
|
193
246
|
);
|
|
194
247
|
|
|
195
|
-
|
|
196
|
-
for (const [key, value] of Object.entries(basketItem.attributes)) {
|
|
197
|
-
if (value === '') {
|
|
198
|
-
setHasGiftPack(false);
|
|
199
|
-
setHasNote((prevstate) => ({ ...prevstate, state: false }));
|
|
200
|
-
setNote('');
|
|
201
|
-
setTextAreaCount(0);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (key) {
|
|
206
|
-
changeNoteTitle(value);
|
|
207
|
-
setNote(value);
|
|
208
|
-
setHasGiftPack(true);
|
|
209
|
-
setTextAreaCount(value?.length);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}, [basketItem.attributes]);
|
|
213
|
-
|
|
214
|
-
useEffect(() => {
|
|
215
|
-
const subscription = watch(({ message }) => {
|
|
216
|
-
setNote(message);
|
|
217
|
-
setTextAreaCount(message.length);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
return () => subscription.unsubscribe();
|
|
221
|
-
}, [watch]);
|
|
222
|
-
|
|
223
|
-
return (
|
|
248
|
+
const defaultRender = () => (
|
|
224
249
|
<div
|
|
225
|
-
className={twMerge(
|
|
226
|
-
clsx(
|
|
227
|
-
'mt-4 sm:mt-0',
|
|
228
|
-
{
|
|
229
|
-
'sm:mt-8': hasNote.state
|
|
230
|
-
},
|
|
231
|
-
className
|
|
232
|
-
)
|
|
233
|
-
)}
|
|
250
|
+
className={twMerge(clsx('mt-4', { 'md:mt-8': hasNote.state }, className))}
|
|
234
251
|
>
|
|
235
252
|
<div className="flex gap-4">
|
|
236
253
|
<div className="flex items-center gap-2">
|
|
@@ -239,7 +256,6 @@ export const BasketGiftPack = ({
|
|
|
239
256
|
size={15}
|
|
240
257
|
className={clsx(hasGiftPack ? 'text-[#e85150]' : 'text-[#000000]')}
|
|
241
258
|
/>
|
|
242
|
-
|
|
243
259
|
{hasGiftPack ? (
|
|
244
260
|
<span className="text-[0.75rem]">
|
|
245
261
|
{_translations.giftPackAdded}
|
|
@@ -249,39 +265,40 @@ export const BasketGiftPack = ({
|
|
|
249
265
|
appearance="ghost"
|
|
250
266
|
className="text-[#000000] cursor-pointer underline border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]"
|
|
251
267
|
onClick={addGiftPack}
|
|
268
|
+
data-testid="add-basket-gift-pack"
|
|
252
269
|
>
|
|
253
270
|
{_translations.addGiftPack}
|
|
254
271
|
</Button>
|
|
255
272
|
)}
|
|
256
273
|
</div>
|
|
257
|
-
<Button
|
|
258
|
-
appearance="ghost"
|
|
259
|
-
className={clsx(
|
|
260
|
-
'text-[#000000] underline cursor-pointer border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]',
|
|
261
|
-
{
|
|
262
|
-
hidden: !hasGiftPack
|
|
263
|
-
}
|
|
264
|
-
)}
|
|
265
|
-
onClick={() =>
|
|
266
|
-
setHasNote((prevstate) => ({ ...prevstate, state: true }))
|
|
267
|
-
}
|
|
268
|
-
>
|
|
269
|
-
{hasNote.title}
|
|
270
|
-
</Button>
|
|
271
274
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
275
|
+
{hasGiftPack && (
|
|
276
|
+
<>
|
|
277
|
+
<Button
|
|
278
|
+
appearance="ghost"
|
|
279
|
+
className="text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] select-none underline h-auto hover:bg-transparent hover:text-[#000000]"
|
|
280
|
+
onClick={() => setHasNote({ ...hasNote, state: true })}
|
|
281
|
+
data-testid="add-basket-gift-pack-note"
|
|
282
|
+
>
|
|
283
|
+
{hasNote.title}
|
|
284
|
+
</Button>
|
|
285
|
+
<Button
|
|
286
|
+
appearance="ghost"
|
|
287
|
+
className={clsx(
|
|
288
|
+
'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
|
|
289
|
+
{
|
|
290
|
+
hidden: !hasGiftPack
|
|
291
|
+
}
|
|
292
|
+
)}
|
|
293
|
+
onClick={removeGiftPack}
|
|
294
|
+
data-testid="remove-basket-gift-pack"
|
|
295
|
+
>
|
|
296
|
+
{_translations.removeGiftPack}
|
|
297
|
+
</Button>
|
|
298
|
+
</>
|
|
299
|
+
)}
|
|
284
300
|
</div>
|
|
301
|
+
|
|
285
302
|
{useModal ? (
|
|
286
303
|
<Modal
|
|
287
304
|
portalId="basket-gift-pack-modal"
|
|
@@ -291,23 +308,30 @@ export const BasketGiftPack = ({
|
|
|
291
308
|
modalClassName
|
|
292
309
|
)}
|
|
293
310
|
open={hasNote.state}
|
|
294
|
-
setOpen={(state) =>
|
|
295
|
-
setHasNote((prevstate) => ({ ...prevstate, state }))
|
|
296
|
-
}
|
|
311
|
+
setOpen={(state) => setHasNote((prev) => ({ ...prev, state }))}
|
|
297
312
|
>
|
|
298
313
|
<div className={twMerge('px-6 py-4', modalContentClassName)}>
|
|
299
314
|
{formContent}
|
|
300
315
|
</div>
|
|
301
316
|
</Modal>
|
|
302
|
-
) : (
|
|
303
|
-
<div
|
|
304
|
-
|
|
305
|
-
hidden: !hasNote.state
|
|
306
|
-
})}
|
|
307
|
-
>
|
|
308
|
-
{formContent}
|
|
309
|
-
</div>
|
|
310
|
-
)}
|
|
317
|
+
) : hasNote.state ? (
|
|
318
|
+
<div className="mt-4">{formContent}</div>
|
|
319
|
+
) : null}
|
|
311
320
|
</div>
|
|
312
321
|
);
|
|
322
|
+
|
|
323
|
+
return customUIRender
|
|
324
|
+
? customUIRender({
|
|
325
|
+
hasGiftPack,
|
|
326
|
+
hasNote,
|
|
327
|
+
note,
|
|
328
|
+
textAreaCount,
|
|
329
|
+
onAddGiftPack: addGiftPack,
|
|
330
|
+
onRemoveGiftPack: removeGiftPack,
|
|
331
|
+
onAddNote: () => setHasNote({ ...hasNote, state: true }),
|
|
332
|
+
onRemoveNote: removeNote,
|
|
333
|
+
formContent,
|
|
334
|
+
translations: _translations
|
|
335
|
+
})
|
|
336
|
+
: defaultRender();
|
|
313
337
|
};
|