@invoice-sdk/widget 0.0.0 → 1.5.2
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/package.json +5 -5
- package/src/components/button.tsx +22 -22
- package/src/components/form/custom-checkbox.tsx +20 -20
- package/src/components/form/file-upload.tsx +140 -140
- package/src/components/form/input-field.tsx +34 -34
- package/src/components/form/select-option.tsx +74 -74
- package/src/components/layout.tsx +13 -13
- package/src/components/process.tsx +20 -20
- package/src/index.ts +1 -1
- package/src/pages/register.tsx +222 -222
- package/src/pages/select-plan.tsx +39 -39
- package/src/pages/select-provider.tsx +73 -73
- package/src/pages/status.tsx +8 -8
- package/src/store/process.ts +17 -17
- package/src/store/register.ts +59 -59
- package/tsconfig.json +19 -19
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { useProcessStore } from "../store/process";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const MAX_STEP = 4;
|
|
5
|
-
|
|
6
|
-
const Process = () => {
|
|
7
|
-
const { step } = useProcessStore();
|
|
8
|
-
return (
|
|
9
|
-
<div className="w-full relative h-3 bg-gray-200 rounded-full">
|
|
10
|
-
<div className="absolute rounded-full bg-green-500"
|
|
11
|
-
style={{
|
|
12
|
-
width: `${(step / MAX_STEP) * 100}%`,
|
|
13
|
-
height: '100%',
|
|
14
|
-
transition: 'width 0.3s ease-in-out'
|
|
15
|
-
}}
|
|
16
|
-
></div>
|
|
17
|
-
</div>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
1
|
+
import { useProcessStore } from "../store/process";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const MAX_STEP = 4;
|
|
5
|
+
|
|
6
|
+
const Process = () => {
|
|
7
|
+
const { step } = useProcessStore();
|
|
8
|
+
return (
|
|
9
|
+
<div className="w-full relative h-3 bg-gray-200 rounded-full">
|
|
10
|
+
<div className="absolute rounded-full bg-green-500"
|
|
11
|
+
style={{
|
|
12
|
+
width: `${(step / MAX_STEP) * 100}%`,
|
|
13
|
+
height: '100%',
|
|
14
|
+
transition: 'width 0.3s ease-in-out'
|
|
15
|
+
}}
|
|
16
|
+
></div>
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
21
|
export default Process
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import InvoiceRegisterWidget from './App'
|
|
1
|
+
import InvoiceRegisterWidget from './App'
|
|
2
2
|
export default InvoiceRegisterWidget;
|
package/src/pages/register.tsx
CHANGED
|
@@ -1,222 +1,222 @@
|
|
|
1
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
2
|
-
import type { SubmitHandler } from 'react-hook-form';
|
|
3
|
-
import { Controller, useForm } from 'react-hook-form';
|
|
4
|
-
import { useNavigate } from 'react-router-dom';
|
|
5
|
-
import z from "zod";
|
|
6
|
-
import Button from '../components/button';
|
|
7
|
-
import FileUpload from '../components/form/file-upload';
|
|
8
|
-
import InputField from '../components/form/input-field';
|
|
9
|
-
import { useProcessStore } from '../store/process';
|
|
10
|
-
import { useRegisterStore } from '../store/register';
|
|
11
|
-
|
|
12
|
-
const formSchema = z.object({
|
|
13
|
-
taxCode: z.string().nonempty('Mã số thuế là bắt buộc'),
|
|
14
|
-
representative: z.string().nonempty('Người đại diện là bắt buộc'),
|
|
15
|
-
email: z
|
|
16
|
-
.string()
|
|
17
|
-
.nonempty('Email là bắt buộc')
|
|
18
|
-
.email('Email không hợp lệ'),
|
|
19
|
-
address: z.string().nonempty('Địa chỉ là bắt buộc'),
|
|
20
|
-
companyName: z.string().nonempty('Tên công ty là bắt buộc'),
|
|
21
|
-
position: z.string().optional(),
|
|
22
|
-
phone: z
|
|
23
|
-
.string()
|
|
24
|
-
.regex(/^[0-9()+\-\s]+$/, 'SĐT không hợp lệ')
|
|
25
|
-
.optional(),
|
|
26
|
-
|
|
27
|
-
// ← here we make it `.optional()`
|
|
28
|
-
license: z
|
|
29
|
-
.instanceof(File, {
|
|
30
|
-
message: 'Giấy phép đăng ký kinh doanh là bắt buộc',
|
|
31
|
-
})
|
|
32
|
-
.optional(),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
export type FormValues = z.infer<typeof formSchema>;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const RegistrationForm = () => {
|
|
39
|
-
const navigate = useNavigate();
|
|
40
|
-
const form = useRegisterStore((state) => state.form);
|
|
41
|
-
const {
|
|
42
|
-
control,
|
|
43
|
-
handleSubmit,
|
|
44
|
-
formState: { errors, isSubmitting, isValid },
|
|
45
|
-
} = useForm<FormValues>({
|
|
46
|
-
resolver: zodResolver(formSchema),
|
|
47
|
-
defaultValues: {
|
|
48
|
-
taxCode: form.taxCode || '',
|
|
49
|
-
representative: form.representative || '',
|
|
50
|
-
email: form.email || '',
|
|
51
|
-
address: form.address || '',
|
|
52
|
-
companyName: form.companyName || '',
|
|
53
|
-
position: form.position || '',
|
|
54
|
-
phone: form.phoneNumber || '',
|
|
55
|
-
license: form.license || undefined, // handle optional license
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const setForm = useRegisterStore((state) => state.setForm);
|
|
60
|
-
const nextStep = useProcessStore((state) => state.nextStep);
|
|
61
|
-
const prevStep = useProcessStore((state) => state.prevStep);
|
|
62
|
-
|
|
63
|
-
const onSubmit: SubmitHandler<FormValues> = (data) => {
|
|
64
|
-
// here data.license is a File
|
|
65
|
-
console.log(data);
|
|
66
|
-
|
|
67
|
-
setForm({
|
|
68
|
-
taxCode: data.taxCode,
|
|
69
|
-
representative: data.representative,
|
|
70
|
-
email: data.email,
|
|
71
|
-
address: data.address,
|
|
72
|
-
companyName: data.companyName,
|
|
73
|
-
position: data.position,
|
|
74
|
-
phoneNumber: data.phone || null, // handle optional phone
|
|
75
|
-
license: data.license || null, // handle optional license
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<form
|
|
82
|
-
onSubmit={handleSubmit(onSubmit)}
|
|
83
|
-
className="w-full mx-auto p-6 bg-white shadow rounded"
|
|
84
|
-
>
|
|
85
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
86
|
-
{/* Left */}
|
|
87
|
-
<div className="space-y-4">
|
|
88
|
-
<Controller
|
|
89
|
-
name="taxCode"
|
|
90
|
-
control={control}
|
|
91
|
-
render={({ field }) => (
|
|
92
|
-
<InputField
|
|
93
|
-
{...field}
|
|
94
|
-
label="Mã số thuế"
|
|
95
|
-
required
|
|
96
|
-
error={errors.taxCode?.message}
|
|
97
|
-
/>
|
|
98
|
-
)}
|
|
99
|
-
/>
|
|
100
|
-
|
|
101
|
-
<Controller
|
|
102
|
-
name="representative"
|
|
103
|
-
control={control}
|
|
104
|
-
render={({ field }) => (
|
|
105
|
-
<InputField
|
|
106
|
-
{...field}
|
|
107
|
-
label="Người đại diện"
|
|
108
|
-
required
|
|
109
|
-
error={errors.representative?.message}
|
|
110
|
-
/>
|
|
111
|
-
)}
|
|
112
|
-
/>
|
|
113
|
-
|
|
114
|
-
<Controller
|
|
115
|
-
name="email"
|
|
116
|
-
control={control}
|
|
117
|
-
render={({ field }) => (
|
|
118
|
-
<InputField
|
|
119
|
-
{...field}
|
|
120
|
-
label="Email"
|
|
121
|
-
type="email"
|
|
122
|
-
required
|
|
123
|
-
error={errors.email?.message}
|
|
124
|
-
/>
|
|
125
|
-
)}
|
|
126
|
-
/>
|
|
127
|
-
|
|
128
|
-
<Controller
|
|
129
|
-
name="address"
|
|
130
|
-
control={control}
|
|
131
|
-
render={({ field }) => (
|
|
132
|
-
<InputField
|
|
133
|
-
{...field}
|
|
134
|
-
label="Địa chỉ"
|
|
135
|
-
required
|
|
136
|
-
error={errors.address?.message}
|
|
137
|
-
/>
|
|
138
|
-
)}
|
|
139
|
-
/>
|
|
140
|
-
|
|
141
|
-
<Controller
|
|
142
|
-
name="license"
|
|
143
|
-
control={control}
|
|
144
|
-
render={({ field }) => (
|
|
145
|
-
<FileUpload
|
|
146
|
-
label="Giấy phép đăng ký kinh doanh"
|
|
147
|
-
required
|
|
148
|
-
file={field.value ?? null}
|
|
149
|
-
onFileChange={field.onChange}
|
|
150
|
-
error={errors.license?.message}
|
|
151
|
-
/>
|
|
152
|
-
)}
|
|
153
|
-
/>
|
|
154
|
-
</div>
|
|
155
|
-
|
|
156
|
-
{/* Right */}
|
|
157
|
-
<div className="space-y-4">
|
|
158
|
-
<Controller
|
|
159
|
-
name="companyName"
|
|
160
|
-
control={control}
|
|
161
|
-
render={({ field }) => (
|
|
162
|
-
<InputField
|
|
163
|
-
{...field}
|
|
164
|
-
label="Tên công ty"
|
|
165
|
-
required
|
|
166
|
-
error={errors.companyName?.message}
|
|
167
|
-
/>
|
|
168
|
-
)}
|
|
169
|
-
/>
|
|
170
|
-
|
|
171
|
-
<Controller
|
|
172
|
-
name="position"
|
|
173
|
-
control={control}
|
|
174
|
-
render={({ field }) => (
|
|
175
|
-
<InputField
|
|
176
|
-
{...field}
|
|
177
|
-
label="Chức vụ"
|
|
178
|
-
error={errors.position?.message}
|
|
179
|
-
/>
|
|
180
|
-
)}
|
|
181
|
-
/>
|
|
182
|
-
|
|
183
|
-
<Controller
|
|
184
|
-
name="phone"
|
|
185
|
-
control={control}
|
|
186
|
-
render={({ field }) => (
|
|
187
|
-
<InputField
|
|
188
|
-
{...field}
|
|
189
|
-
label="SĐT"
|
|
190
|
-
type="tel"
|
|
191
|
-
error={errors.phone?.message}
|
|
192
|
-
/>
|
|
193
|
-
)}
|
|
194
|
-
/>
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
|
|
198
|
-
<div className='flex items-center justify-end gap-2'>
|
|
199
|
-
<Button title={'Back'}
|
|
200
|
-
handleClick={() => {
|
|
201
|
-
prevStep()
|
|
202
|
-
navigate('/select-provider');
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
className=' !bg-gray-200 !text-gray-700 hover:!bg-gray-300 disabled:!bg-gray-200 disabled:!text-gray-500'
|
|
207
|
-
/>
|
|
208
|
-
<Button
|
|
209
|
-
type='submit'
|
|
210
|
-
title={isSubmitting ? 'Submitting...' : 'Submit'} isDisabled={isSubmitting || Object.keys(errors).length > 0 || !isValid}
|
|
211
|
-
handleClick={() => {
|
|
212
|
-
nextStep()
|
|
213
|
-
navigate('/select-plan');
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/>
|
|
217
|
-
</div>
|
|
218
|
-
</form>
|
|
219
|
-
);
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
export default RegistrationForm;
|
|
1
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
2
|
+
import type { SubmitHandler } from 'react-hook-form';
|
|
3
|
+
import { Controller, useForm } from 'react-hook-form';
|
|
4
|
+
import { useNavigate } from 'react-router-dom';
|
|
5
|
+
import z from "zod";
|
|
6
|
+
import Button from '../components/button';
|
|
7
|
+
import FileUpload from '../components/form/file-upload';
|
|
8
|
+
import InputField from '../components/form/input-field';
|
|
9
|
+
import { useProcessStore } from '../store/process';
|
|
10
|
+
import { useRegisterStore } from '../store/register';
|
|
11
|
+
|
|
12
|
+
const formSchema = z.object({
|
|
13
|
+
taxCode: z.string().nonempty('Mã số thuế là bắt buộc'),
|
|
14
|
+
representative: z.string().nonempty('Người đại diện là bắt buộc'),
|
|
15
|
+
email: z
|
|
16
|
+
.string()
|
|
17
|
+
.nonempty('Email là bắt buộc')
|
|
18
|
+
.email('Email không hợp lệ'),
|
|
19
|
+
address: z.string().nonempty('Địa chỉ là bắt buộc'),
|
|
20
|
+
companyName: z.string().nonempty('Tên công ty là bắt buộc'),
|
|
21
|
+
position: z.string().optional(),
|
|
22
|
+
phone: z
|
|
23
|
+
.string()
|
|
24
|
+
.regex(/^[0-9()+\-\s]+$/, 'SĐT không hợp lệ')
|
|
25
|
+
.optional(),
|
|
26
|
+
|
|
27
|
+
// ← here we make it `.optional()`
|
|
28
|
+
license: z
|
|
29
|
+
.instanceof(File, {
|
|
30
|
+
message: 'Giấy phép đăng ký kinh doanh là bắt buộc',
|
|
31
|
+
})
|
|
32
|
+
.optional(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export type FormValues = z.infer<typeof formSchema>;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const RegistrationForm = () => {
|
|
39
|
+
const navigate = useNavigate();
|
|
40
|
+
const form = useRegisterStore((state) => state.form);
|
|
41
|
+
const {
|
|
42
|
+
control,
|
|
43
|
+
handleSubmit,
|
|
44
|
+
formState: { errors, isSubmitting, isValid },
|
|
45
|
+
} = useForm<FormValues>({
|
|
46
|
+
resolver: zodResolver(formSchema),
|
|
47
|
+
defaultValues: {
|
|
48
|
+
taxCode: form.taxCode || '',
|
|
49
|
+
representative: form.representative || '',
|
|
50
|
+
email: form.email || '',
|
|
51
|
+
address: form.address || '',
|
|
52
|
+
companyName: form.companyName || '',
|
|
53
|
+
position: form.position || '',
|
|
54
|
+
phone: form.phoneNumber || '',
|
|
55
|
+
license: form.license || undefined, // handle optional license
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const setForm = useRegisterStore((state) => state.setForm);
|
|
60
|
+
const nextStep = useProcessStore((state) => state.nextStep);
|
|
61
|
+
const prevStep = useProcessStore((state) => state.prevStep);
|
|
62
|
+
|
|
63
|
+
const onSubmit: SubmitHandler<FormValues> = (data) => {
|
|
64
|
+
// here data.license is a File
|
|
65
|
+
console.log(data);
|
|
66
|
+
|
|
67
|
+
setForm({
|
|
68
|
+
taxCode: data.taxCode,
|
|
69
|
+
representative: data.representative,
|
|
70
|
+
email: data.email,
|
|
71
|
+
address: data.address,
|
|
72
|
+
companyName: data.companyName,
|
|
73
|
+
position: data.position,
|
|
74
|
+
phoneNumber: data.phone || null, // handle optional phone
|
|
75
|
+
license: data.license || null, // handle optional license
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<form
|
|
82
|
+
onSubmit={handleSubmit(onSubmit)}
|
|
83
|
+
className="w-full mx-auto p-6 bg-white shadow rounded"
|
|
84
|
+
>
|
|
85
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
86
|
+
{/* Left */}
|
|
87
|
+
<div className="space-y-4">
|
|
88
|
+
<Controller
|
|
89
|
+
name="taxCode"
|
|
90
|
+
control={control}
|
|
91
|
+
render={({ field }) => (
|
|
92
|
+
<InputField
|
|
93
|
+
{...field}
|
|
94
|
+
label="Mã số thuế"
|
|
95
|
+
required
|
|
96
|
+
error={errors.taxCode?.message}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<Controller
|
|
102
|
+
name="representative"
|
|
103
|
+
control={control}
|
|
104
|
+
render={({ field }) => (
|
|
105
|
+
<InputField
|
|
106
|
+
{...field}
|
|
107
|
+
label="Người đại diện"
|
|
108
|
+
required
|
|
109
|
+
error={errors.representative?.message}
|
|
110
|
+
/>
|
|
111
|
+
)}
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<Controller
|
|
115
|
+
name="email"
|
|
116
|
+
control={control}
|
|
117
|
+
render={({ field }) => (
|
|
118
|
+
<InputField
|
|
119
|
+
{...field}
|
|
120
|
+
label="Email"
|
|
121
|
+
type="email"
|
|
122
|
+
required
|
|
123
|
+
error={errors.email?.message}
|
|
124
|
+
/>
|
|
125
|
+
)}
|
|
126
|
+
/>
|
|
127
|
+
|
|
128
|
+
<Controller
|
|
129
|
+
name="address"
|
|
130
|
+
control={control}
|
|
131
|
+
render={({ field }) => (
|
|
132
|
+
<InputField
|
|
133
|
+
{...field}
|
|
134
|
+
label="Địa chỉ"
|
|
135
|
+
required
|
|
136
|
+
error={errors.address?.message}
|
|
137
|
+
/>
|
|
138
|
+
)}
|
|
139
|
+
/>
|
|
140
|
+
|
|
141
|
+
<Controller
|
|
142
|
+
name="license"
|
|
143
|
+
control={control}
|
|
144
|
+
render={({ field }) => (
|
|
145
|
+
<FileUpload
|
|
146
|
+
label="Giấy phép đăng ký kinh doanh"
|
|
147
|
+
required
|
|
148
|
+
file={field.value ?? null}
|
|
149
|
+
onFileChange={field.onChange}
|
|
150
|
+
error={errors.license?.message}
|
|
151
|
+
/>
|
|
152
|
+
)}
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
{/* Right */}
|
|
157
|
+
<div className="space-y-4">
|
|
158
|
+
<Controller
|
|
159
|
+
name="companyName"
|
|
160
|
+
control={control}
|
|
161
|
+
render={({ field }) => (
|
|
162
|
+
<InputField
|
|
163
|
+
{...field}
|
|
164
|
+
label="Tên công ty"
|
|
165
|
+
required
|
|
166
|
+
error={errors.companyName?.message}
|
|
167
|
+
/>
|
|
168
|
+
)}
|
|
169
|
+
/>
|
|
170
|
+
|
|
171
|
+
<Controller
|
|
172
|
+
name="position"
|
|
173
|
+
control={control}
|
|
174
|
+
render={({ field }) => (
|
|
175
|
+
<InputField
|
|
176
|
+
{...field}
|
|
177
|
+
label="Chức vụ"
|
|
178
|
+
error={errors.position?.message}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
181
|
+
/>
|
|
182
|
+
|
|
183
|
+
<Controller
|
|
184
|
+
name="phone"
|
|
185
|
+
control={control}
|
|
186
|
+
render={({ field }) => (
|
|
187
|
+
<InputField
|
|
188
|
+
{...field}
|
|
189
|
+
label="SĐT"
|
|
190
|
+
type="tel"
|
|
191
|
+
error={errors.phone?.message}
|
|
192
|
+
/>
|
|
193
|
+
)}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<div className='flex items-center justify-end gap-2'>
|
|
199
|
+
<Button title={'Back'}
|
|
200
|
+
handleClick={() => {
|
|
201
|
+
prevStep()
|
|
202
|
+
navigate('/select-provider');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
className=' !bg-gray-200 !text-gray-700 hover:!bg-gray-300 disabled:!bg-gray-200 disabled:!text-gray-500'
|
|
207
|
+
/>
|
|
208
|
+
<Button
|
|
209
|
+
type='submit'
|
|
210
|
+
title={isSubmitting ? 'Submitting...' : 'Submit'} isDisabled={isSubmitting || Object.keys(errors).length > 0 || !isValid}
|
|
211
|
+
handleClick={() => {
|
|
212
|
+
nextStep()
|
|
213
|
+
navigate('/select-plan');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
</form>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export default RegistrationForm;
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import { useNavigate } from "react-router-dom";
|
|
3
|
-
import Button from "../components/button";
|
|
4
|
-
import SubscriptionSelector from "../components/form/select-option";
|
|
5
|
-
import { useProcessStore } from "../store/process";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const SelectPlan = () => {
|
|
9
|
-
const navigate = useNavigate();
|
|
10
|
-
const nextStep = useProcessStore((state) => state.nextStep);
|
|
11
|
-
const [plan, setPlan] = useState('300');
|
|
12
|
-
const options = [
|
|
13
|
-
{ value: '100', label: '100 đơn/tháng' },
|
|
14
|
-
{ value: '300', label: '300 đơn/tháng' },
|
|
15
|
-
{ value: '500', label: '500 đơn/tháng' },
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<div className="w-full flex flex-col gap-6">
|
|
20
|
-
<h2 className="heading">Select subscription package</h2>
|
|
21
|
-
<SubscriptionSelector
|
|
22
|
-
options={options}
|
|
23
|
-
value={plan}
|
|
24
|
-
onChange={setPlan}
|
|
25
|
-
/>
|
|
26
|
-
<div className='text-right'>
|
|
27
|
-
<Button title={'Next'}
|
|
28
|
-
isDisabled={!plan}
|
|
29
|
-
handleClick={() => {
|
|
30
|
-
nextStep()
|
|
31
|
-
navigate("/status")
|
|
32
|
-
}}
|
|
33
|
-
/>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export default SelectPlan;
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { useNavigate } from "react-router-dom";
|
|
3
|
+
import Button from "../components/button";
|
|
4
|
+
import SubscriptionSelector from "../components/form/select-option";
|
|
5
|
+
import { useProcessStore } from "../store/process";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const SelectPlan = () => {
|
|
9
|
+
const navigate = useNavigate();
|
|
10
|
+
const nextStep = useProcessStore((state) => state.nextStep);
|
|
11
|
+
const [plan, setPlan] = useState('300');
|
|
12
|
+
const options = [
|
|
13
|
+
{ value: '100', label: '100 đơn/tháng' },
|
|
14
|
+
{ value: '300', label: '300 đơn/tháng' },
|
|
15
|
+
{ value: '500', label: '500 đơn/tháng' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="w-full flex flex-col gap-6">
|
|
20
|
+
<h2 className="heading">Select subscription package</h2>
|
|
21
|
+
<SubscriptionSelector
|
|
22
|
+
options={options}
|
|
23
|
+
value={plan}
|
|
24
|
+
onChange={setPlan}
|
|
25
|
+
/>
|
|
26
|
+
<div className='text-right'>
|
|
27
|
+
<Button title={'Next'}
|
|
28
|
+
isDisabled={!plan}
|
|
29
|
+
handleClick={() => {
|
|
30
|
+
nextStep()
|
|
31
|
+
navigate("/status")
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default SelectPlan;
|