@akinon/pz-basket-gift-pack 1.99.0-rc.70 → 1.99.0-snapshot-ZERO-3640-20250919140935

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 CHANGED
@@ -1,27 +1,6 @@
1
1
  # @akinon/pz-basket-gift-pack
2
2
 
3
- ## 1.99.0-rc.70
4
-
5
- ## 1.99.0-rc.69
6
-
7
- ## 1.99.0-rc.68
8
-
9
- ## 1.99.0-rc.67
10
-
11
- ## 1.99.0-rc.66
12
-
13
- ### Minor Changes
14
-
15
- - 72bfcbf2: ZERO-3347: Manage save button disable status
16
- - d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
17
- - 2ba89b3c: ZERO-3361: Refactor basket gift pack component
18
- - 16aff543: ZERO-3431: Add test script for redirect utility in package.json
19
- - 64699d3ff: ZERO-2761: Fix invalid import for plugin module
20
- - e974d8e8: ZERO-3406: Fix rc build
21
- - 7eb51ca9: ZERO-3424 :Update package versions
22
- - 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
23
- - 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
24
- - 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
3
+ ## 1.99.0-snapshot-ZERO-3640-20250919140935
25
4
 
26
5
  ## 1.98.0
27
6
 
package/README.md CHANGED
@@ -19,143 +19,3 @@ 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,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/pz-basket-gift-pack",
3
- "version": "1.99.0-rc.70",
3
+ "version": "1.99.0-snapshot-ZERO-3640-20250919140935",
4
4
  "license": "MIT",
5
5
  "main": "src/index.tsx",
6
6
  "peerDependencies": {
package/src/index.tsx CHANGED
@@ -4,69 +4,38 @@ import {
4
4
  } from './endpoints';
5
5
  import clsx from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
- import {
8
- useForm,
9
- SubmitHandler,
10
- UseFormRegister,
11
- FieldErrors,
12
- UseFormHandleSubmit
13
- } from 'react-hook-form';
7
+ import { useForm, SubmitHandler } from 'react-hook-form';
14
8
  import { yupResolver } from '@hookform/resolvers/yup';
15
9
  import * as yup from 'yup';
16
10
  import { useEffect, useState } from 'react';
17
11
  import { Button, Icon, Modal } from '@akinon/next/components';
18
12
  import { BasketItem as BasketItemType } from '@akinon/next/types';
19
13
 
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
-
37
14
  interface GiftPackForm {
38
15
  message: string;
39
16
  }
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
- }
17
+
52
18
  interface Props {
53
19
  basketItem: BasketItemType;
54
20
  useModal?: boolean;
55
21
  modalTitle?: string;
56
22
  modalClassName?: string;
57
23
  modalContentClassName?: string;
58
- translations?: Partial<typeof defaultTranslations>;
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
+ };
59
38
  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;
70
39
  }
71
40
 
72
41
  export const BasketGiftPack = ({
@@ -76,13 +45,30 @@ export const BasketGiftPack = ({
76
45
  useModal = false,
77
46
  modalTitle = 'Gift Note',
78
47
  modalClassName,
79
- modalContentClassName,
80
- customUIRender,
81
- customGiftNoteFormUIRender
48
+ modalContentClassName
82
49
  }: Props) => {
83
- const _translations = { ...defaultTranslations, ...translations };
84
- const [addGiftPackage, { isLoading: isAddingGiftPackage }] =
85
- useAddGiftPackageMutation();
50
+ const defaultTranslations = {
51
+ placeholderInput:
52
+ 'You can leave this area empty. However it will be a gift package without note.',
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();
86
72
  const [removeGiftPackage] = useRemoveGiftPackageMutation();
87
73
  const [hasGiftPack, setHasGiftPack] = useState(false);
88
74
  const [hasNote, setHasNote] = useState({
@@ -93,9 +79,10 @@ export const BasketGiftPack = ({
93
79
  const [note, setNote] = useState('');
94
80
  const defaultMessage = 'NO-GIFT-NOTE';
95
81
 
96
- const schema = yup.object().shape({
97
- message: yup.string().max(160, _translations.warningMessage)
98
- });
82
+ const giftPackFormSchema = () =>
83
+ yup.object().shape({
84
+ message: yup.string().max(160, _translations.warningMessage)
85
+ });
99
86
 
100
87
  const {
101
88
  register,
@@ -103,83 +90,54 @@ export const BasketGiftPack = ({
103
90
  handleSubmit,
104
91
  formState: { errors }
105
92
  } = useForm<GiftPackForm>({
106
- resolver: yupResolver(schema)
93
+ resolver: yupResolver(giftPackFormSchema())
107
94
  });
108
95
 
109
96
  const onSubmit: SubmitHandler<GiftPackForm> = async (data) => {
110
- await addGiftPackage({ id: basketItem.id, message: data.message }).unwrap();
111
- setHasNote({ ...hasNote, state: false });
112
- changeNoteTitle(data.message);
97
+ addGiftPackage({ id: basketItem.id, message: data.message })
98
+ .unwrap()
99
+ .then(() => {
100
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
101
+ changeNoteTitle(data.message);
102
+ });
113
103
  };
114
104
 
115
- const addGiftPack = async () => {
116
- await addGiftPackage({
117
- id: basketItem.id,
118
- message: defaultMessage
119
- }).unwrap();
120
- setHasGiftPack(true);
121
- setHasNote({ ...hasNote, state: false });
105
+ const addGiftPack = () => {
106
+ addGiftPackage({ id: basketItem.id, message: defaultMessage })
107
+ .unwrap()
108
+ .then(() => {
109
+ setHasGiftPack(true);
110
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
111
+ });
122
112
  };
123
113
 
124
114
  const removeGiftPack = () => {
125
115
  removeGiftPackage({ id: basketItem.id });
126
116
  setHasGiftPack(false);
127
- setHasNote({ ...hasNote, state: false });
117
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
128
118
  };
129
119
 
130
120
  const removeNote = () => {
131
121
  addGiftPackage({ id: basketItem.id, message: defaultMessage });
132
- setHasNote({ ...hasNote, state: false });
122
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
133
123
  changeNoteTitle(defaultMessage);
134
124
  };
135
125
 
136
- const changeNoteTitle = (value: string) => {
137
- const title =
138
- value !== defaultMessage
139
- ? _translations.changeNote
140
- : _translations.addNote;
141
- setHasNote((prev) => ({ ...prev, title }));
142
- };
143
-
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
- }
126
+ const changeNoteTitle = (value) => {
127
+ if (value !== defaultMessage) {
128
+ setHasNote((prevstate) => ({
129
+ ...prevstate,
130
+ title: _translations.changeNote
131
+ }));
132
+ } else {
133
+ setHasNote((prevstate) => ({
134
+ ...prevstate,
135
+ title: _translations.addNote
136
+ }));
160
137
  }
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]);
138
+ };
171
139
 
172
- const formContent = customGiftNoteFormUIRender ? (
173
- customGiftNoteFormUIRender({
174
- register,
175
- errors,
176
- note,
177
- textAreaCount,
178
- onSubmit: () => handleSubmit(onSubmit)(),
179
- removeNote,
180
- handleSubmit
181
- })
182
- ) : (
140
+ const formContent = (
183
141
  <form onSubmit={handleSubmit(onSubmit)}>
184
142
  {!useModal && (
185
143
  <div className="flex justify-between mb-3">
@@ -191,7 +149,7 @@ export const BasketGiftPack = ({
191
149
  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]"
192
150
  onClick={(e) => {
193
151
  e.preventDefault();
194
- setHasNote({ ...hasNote, state: false });
152
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
195
153
  }}
196
154
  >
197
155
  {_translations.close}
@@ -199,26 +157,27 @@ export const BasketGiftPack = ({
199
157
  </div>
200
158
  )}
201
159
  <textarea
202
- className="w-full border border-[#4a4f53] p-4 text-[0.75rem] placeholder:text-[#c8c9c8]"
160
+ className="w-full border border-solid border-[#4a4f53] p-4 placeholder:text-[0.75rem] placeholder:text-[#c8c9c8] outline-none text-[0.75rem]"
203
161
  rows={7}
162
+ name="message"
163
+ value={note !== defaultMessage ? note : ' '}
204
164
  placeholder={_translations.placeholderInput}
205
165
  {...register('message')}
206
- value={note !== defaultMessage ? note : ''}
207
166
  data-testid="basket-gift-pack-note-input"
208
167
  />
209
168
  {errors.message && (
210
169
  <span className="text-sm text-[#d72a04]">{errors.message.message}</span>
211
170
  )}
212
- <div className="flex justify-between mt-2 items-center">
171
+ <div className="flex justify-between items-center mt-2">
213
172
  <span
214
173
  className={clsx(
215
- 'text-[0.75rem]',
174
+ 'text-[0.75rem] ',
216
175
  textAreaCount > 160 ? 'text-[#e85150]' : 'text-[#82a27c]'
217
176
  )}
218
177
  >
219
178
  {textAreaCount}/160 {_translations.charactersLength}
220
179
  </span>
221
- <div className="flex gap-3 items-center">
180
+ <div className="flex items-center gap-3">
222
181
  <Button
223
182
  appearance="ghost"
224
183
  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]"
@@ -231,24 +190,52 @@ export const BasketGiftPack = ({
231
190
  type="submit"
232
191
  className="w-28 h-7 font-medium uppercase"
233
192
  data-testid="basket-gift-pack-note-save-button"
234
- disabled={
235
- isAddingGiftPackage ||
236
- textAreaCount === 0 ||
237
- note.trim() === '' ||
238
- note === defaultMessage
239
- }
240
193
  >
241
- {isAddingGiftPackage ? _translations.saving : _translations.save}
194
+ {_translations.save}
242
195
  </Button>
243
196
  </div>
244
197
  </div>
245
198
  </form>
246
199
  );
247
200
 
248
- const defaultRender = () => (
201
+ useEffect(() => {
202
+ for (const [key, value] of Object.entries(basketItem.attributes)) {
203
+ if (value === '') {
204
+ setHasGiftPack(false);
205
+ setHasNote((prevstate) => ({ ...prevstate, state: false }));
206
+ setNote('');
207
+ setTextAreaCount(0);
208
+ return;
209
+ }
210
+
211
+ if (key) {
212
+ changeNoteTitle(value);
213
+ setNote(value);
214
+ setHasGiftPack(true);
215
+ setTextAreaCount(value?.length);
216
+ }
217
+ }
218
+ }, [basketItem.attributes]);
219
+
220
+ useEffect(() => {
221
+ const subscription = watch(({ message }) => {
222
+ setNote(message);
223
+ setTextAreaCount(message.length);
224
+ });
225
+
226
+ return () => subscription.unsubscribe();
227
+ }, [watch]);
228
+
229
+ return (
249
230
  <div
250
231
  className={twMerge(
251
- clsx('mt-4 sm:mt-0', { 'sm:mt-8': hasNote.state }, className)
232
+ clsx(
233
+ 'mt-4 sm:mt-0',
234
+ {
235
+ 'sm:mt-8': hasNote.state
236
+ },
237
+ className
238
+ )
252
239
  )}
253
240
  >
254
241
  <div className="flex gap-4">
@@ -258,6 +245,7 @@ export const BasketGiftPack = ({
258
245
  size={15}
259
246
  className={clsx(hasGiftPack ? 'text-[#e85150]' : 'text-[#000000]')}
260
247
  />
248
+
261
249
  {hasGiftPack ? (
262
250
  <span className="text-[0.75rem]">
263
251
  {_translations.giftPackAdded}
@@ -273,34 +261,36 @@ export const BasketGiftPack = ({
273
261
  </Button>
274
262
  )}
275
263
  </div>
264
+ <Button
265
+ appearance="ghost"
266
+ className={clsx(
267
+ 'text-[#000000] underline cursor-pointer border-0 px-0 py-0 text-[0.75rem] h-auto hover:bg-transparent hover:text-[#000000]',
268
+ {
269
+ hidden: !hasGiftPack
270
+ }
271
+ )}
272
+ onClick={() =>
273
+ setHasNote((prevstate) => ({ ...prevstate, state: true }))
274
+ }
275
+ data-testid="add-basket-gift-pack-note"
276
+ >
277
+ {hasNote.title}
278
+ </Button>
276
279
 
277
- {hasGiftPack && (
278
- <>
279
- <Button
280
- appearance="ghost"
281
- 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]"
282
- onClick={() => setHasNote({ ...hasNote, state: true })}
283
- data-testid="add-basket-gift-pack-note"
284
- >
285
- {hasNote.title}
286
- </Button>
287
- <Button
288
- appearance="ghost"
289
- className={clsx(
290
- 'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
291
- {
292
- hidden: !hasGiftPack
293
- }
294
- )}
295
- onClick={removeGiftPack}
296
- data-testid="remove-basket-gift-pack"
297
- >
298
- {_translations.removeGiftPack}
299
- </Button>
300
- </>
301
- )}
280
+ <Button
281
+ appearance="ghost"
282
+ className={clsx(
283
+ 'text-[#000000] cursor-pointer border-0 px-0 py-0 text-[0.75rem] underline h-auto hover:bg-transparent hover:text-[#000000]',
284
+ {
285
+ hidden: !hasGiftPack
286
+ }
287
+ )}
288
+ onClick={removeGiftPack}
289
+ data-testid="remove-basket-gift-pack"
290
+ >
291
+ {_translations.removeGiftPack}
292
+ </Button>
302
293
  </div>
303
-
304
294
  {useModal ? (
305
295
  <Modal
306
296
  portalId="basket-gift-pack-modal"
@@ -310,30 +300,23 @@ export const BasketGiftPack = ({
310
300
  modalClassName
311
301
  )}
312
302
  open={hasNote.state}
313
- setOpen={(state) => setHasNote((prev) => ({ ...prev, state }))}
303
+ setOpen={(state) =>
304
+ setHasNote((prevstate) => ({ ...prevstate, state }))
305
+ }
314
306
  >
315
307
  <div className={twMerge('px-6 py-4', modalContentClassName)}>
316
308
  {formContent}
317
309
  </div>
318
310
  </Modal>
319
- ) : hasNote.state ? (
320
- <div className="mt-4">{formContent}</div>
321
- ) : null}
311
+ ) : (
312
+ <div
313
+ className={clsx('mt-4', {
314
+ hidden: !hasNote.state
315
+ })}
316
+ >
317
+ {formContent}
318
+ </div>
319
+ )}
322
320
  </div>
323
321
  );
324
-
325
- return customUIRender
326
- ? customUIRender({
327
- hasGiftPack,
328
- hasNote,
329
- note,
330
- textAreaCount,
331
- onAddGiftPack: addGiftPack,
332
- onRemoveGiftPack: removeGiftPack,
333
- onAddNote: () => setHasNote({ ...hasNote, state: true }),
334
- onRemoveNote: removeNote,
335
- formContent,
336
- translations: _translations
337
- })
338
- : defaultRender();
339
322
  };