Skip to content

Commit b049d18

Browse files
authored
Merge pull request #201 from w3bdesign/development
Added React Hook Form with validation
2 parents d4954e9 + 1411b6f commit b049d18

File tree

6 files changed

+215
-182
lines changed

6 files changed

+215
-182
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
- Cart handling and checkout with WooCommerce (Cash On Delivery only for now)
3131
- Algolia search
3232
- Apollo Client with GraphQL
33+
- React Hook Form with form validation and error display
3334
- Animations with React-Spring and Animate.css
3435
- Loading spinner created with Styled Components
3536
- Shows page load progress with Nprogress during navigation
@@ -42,8 +43,6 @@
4243
## TODO
4344

4445
- Display product variation name in cart / checkout
45-
- Implement React-hook-form for validation
46-
- Fix bug with changing quantity for variable products
4746
- Hide products not in stock
4847
- Add better SEO
4948
- Add a better README.md

components/Checkout/Billing.component.jsx

Lines changed: 186 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,197 @@
1-
import Error from './Error.component';
1+
import { useForm } from 'react-hook-form';
2+
23
import CheckoutTitle from 'components/Header/CheckoutTitle.component';
34

4-
const Billing = ({ input, handleOnChange }) => {
5-
// https://react-hook-form.com/get-started#Quickstart
5+
const Input = ({
6+
name,
7+
label,
8+
register,
9+
placeholder,
10+
value,
11+
parameters,
12+
type = 'text',
13+
readOnly = false,
14+
}) => (
15+
<>
16+
<label className="pb-4">{label}</label>
17+
<input
18+
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
19+
name={name}
20+
placeholder={placeholder}
21+
type="text"
22+
value={value}
23+
ref={register(parameters)}
24+
type={type}
25+
readOnly={readOnly}
26+
/>
27+
</>
28+
);
29+
30+
const Billing = ({ onSubmit }) => {
31+
const { register, handleSubmit, errors } = useForm();
32+
633
return (
734
<>
835
<section className="relative text-gray-700 body-font">
9-
<div className="container px-5 py-2 mx-auto">
10-
<CheckoutTitle title="Betalingsdetaljer" />
11-
<div className="mx-auto lg:w-1/2 md:w-2/3">
12-
<div className="flex flex-wrap -m-2">
13-
<div className="w-1/2 p-2">
14-
<label className="pb-4">Fornavn</label>
15-
<input
16-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
17-
placeholder="Fornavn"
18-
type="text"
19-
onChange={handleOnChange}
20-
value={input.firstName}
21-
name="firstName"
22-
id="first-name"
23-
/>
24-
<Error errors={input.errors} fieldName={'firstName'} />
25-
</div>
26-
<div className="w-1/2 p-2">
27-
<label className="pb-4">Etternavn</label>
28-
<input
29-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
30-
placeholder="Etternavn"
31-
type="text"
32-
onChange={handleOnChange}
33-
value={input.lastName}
34-
name="lastName"
35-
id="last-name"
36-
/>
37-
<Error errors={input.errors} fieldName={'lastName'} />
38-
</div>
39-
<div className="w-1/2 p-2">
40-
<label className="pb-4">Adresse</label>
41-
<input
42-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
43-
placeholder="Addresse"
44-
type="text"
45-
onChange={handleOnChange}
46-
value={input.address1}
47-
name="address1"
48-
id="address1"
49-
/>
50-
<Error errors={input.errors} fieldName={'address1'} />
51-
</div>
52-
<div className="w-1/2 p-2">
53-
<label className="pb-4">Postnummer</label>
54-
<input
55-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
56-
placeholder="Postnummer"
57-
type="text"
58-
onChange={handleOnChange}
59-
value={input.postcode}
60-
name="postcode"
61-
id="post-code"
62-
/>
63-
<Error errors={input.errors} fieldName={'postcode'} />
64-
</div>
65-
<div className="w-1/2 p-2">
66-
<label className="pb-4">Sted</label>
67-
<input
68-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
69-
placeholder="Sted"
70-
type="text"
71-
onChange={handleOnChange}
72-
value={input.city}
73-
name="city"
74-
id="city"
75-
/>
76-
<Error errors={input.errors} fieldName={'city'} />
77-
</div>
78-
<div className="w-1/2 p-2">
79-
<label className="pb-4">Epost</label>
80-
<input
81-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
82-
placeholder="Epost"
83-
type="text"
84-
onChange={handleOnChange}
85-
value={input.email}
86-
name="email"
87-
id="email"
88-
/>
89-
<Error errors={input.errors} fieldName={'email'} />
90-
</div>
91-
<div className="w-1/2 p-2">
92-
<label className="pb-4">Telefon</label>
93-
<input
94-
className="w-full px-4 py-2 mt-2 text-base bg-white border border-gray-400 rounded focus:outline-none focus:border-black"
95-
placeholder="Telefon"
96-
type="text"
97-
onChange={handleOnChange}
98-
value={input.phone}
99-
name="phone"
100-
id="phone1"
101-
/>
102-
<Error errors={input.errors} fieldName={'phone'} />
103-
</div>
104-
<div className="w-1/2 p-2">
105-
<input
106-
className="hidden"
107-
value="bacs"
108-
name="paymentMethod"
109-
type="radio"
110-
checked
111-
readOnly
112-
/>
113-
</div>
114-
<div className="w-full p-2">
115-
<button className="flex px-4 py-2 mx-auto font-bold bg-white border border-gray-400 border-solid rounded hover:bg-gray-400">
116-
BESTILL
117-
</button>
36+
<form onSubmit={handleSubmit(onSubmit)}>
37+
<div className="container px-5 py-2 mx-auto">
38+
<CheckoutTitle title="Betalingsdetaljer" />
39+
<div className="mx-auto lg:w-1/2 md:w-2/3">
40+
<div className="flex flex-wrap -m-2">
41+
<div className="w-1/2 p-2">
42+
<Input
43+
name="firstName"
44+
placeholder="Fornavn"
45+
label="Fornavn"
46+
register={register}
47+
parameters={{ required: 'Dette feltet er påkrevd' }}
48+
/>
49+
{errors.firstName && (
50+
<span className="text-red-500">
51+
FEIL: {errors.firstName.message}
52+
</span>
53+
)}
54+
</div>
55+
<div className="w-1/2 p-2">
56+
<Input
57+
name="lastName"
58+
placeholder="Etternavn"
59+
label="Etternavn"
60+
register={register}
61+
parameters={{ required: 'Dette feltet er påkrevd' }}
62+
/>
63+
{errors.lastName && (
64+
<span className="text-red-500">
65+
FEIL: {errors.lastName.message}
66+
</span>
67+
)}
68+
</div>
69+
<div className="w-1/2 p-2">
70+
<Input
71+
name="address1"
72+
placeholder="Adresse"
73+
label="Adresse"
74+
register={register}
75+
parameters={{ required: 'Dette feltet er påkrevd' }}
76+
/>
77+
{errors.address1 && (
78+
<span className="text-red-500">
79+
FEIL: {errors.address1.message}
80+
</span>
81+
)}
82+
</div>
83+
<div className="w-1/2 p-2">
84+
<Input
85+
name="postcode"
86+
placeholder="Postnummer"
87+
label="Postnummer"
88+
register={register}
89+
parameters={{
90+
required: 'Dette feltet er påkrevd',
91+
minLength: {
92+
value: 4,
93+
message: 'Postnummer må være minimum 4 tall',
94+
},
95+
maxLength: {
96+
value: 4,
97+
message: 'Postnummer må være maksimalt 4 tall',
98+
},
99+
pattern: {
100+
value: /^[0-9]+$/i,
101+
message: 'Postnummer må bare være tall',
102+
},
103+
}}
104+
/>
105+
{errors.postcode && (
106+
<span className="text-red-500">
107+
FEIL: {errors.postcode.message}
108+
</span>
109+
)}
110+
</div>
111+
<div className="w-1/2 p-2">
112+
<Input
113+
name="city"
114+
placeholder="Sted"
115+
label="Sted"
116+
register={register}
117+
parameters={{ required: 'Dette feltet er påkrevd' }}
118+
/>
119+
{errors.city && (
120+
<span className="text-red-500">
121+
FEIL: {errors.city.message}
122+
</span>
123+
)}
124+
</div>
125+
<div className="w-1/2 p-2">
126+
<Input
127+
name="email"
128+
placeholder="Epost"
129+
label="Epost"
130+
register={register}
131+
parameters={{
132+
required: 'Dette feltet er påkrevd',
133+
pattern: {
134+
value: /[^@]+@[^@]+\.[^@]+/i,
135+
message: 'Du må oppgi en gyldig epost',
136+
},
137+
}}
138+
/>
139+
{errors.email && (
140+
<span className="text-red-500">
141+
FEIL: {errors.email.message}
142+
</span>
143+
)}
144+
</div>
145+
<div className="w-1/2 p-2">
146+
<Input
147+
name="phone"
148+
placeholder="Telefon"
149+
label="Telefon"
150+
register={register}
151+
parameters={{
152+
required: 'Dette feltet er påkrevd',
153+
minLength: {
154+
value: 8,
155+
message: 'Minimum 8 tall i telefonnummeret',
156+
},
157+
maxLength: {
158+
value: 8,
159+
message: 'Maksimalt 8 tall i telefonnummeret',
160+
},
161+
162+
pattern: {
163+
value: /^[0-9]+$/i,
164+
message: 'Ikke gyldig telefonnummer',
165+
},
166+
}}
167+
/>
168+
{errors.phone && (
169+
<span className="text-red-500">
170+
FEIL: {errors.phone.message}
171+
</span>
172+
)}
173+
</div>
174+
<div className="w-1/2 p-2">
175+
<Input
176+
name="paymentMethod"
177+
placeholder="paymentMethod"
178+
label=""
179+
type="hidden"
180+
value="cod"
181+
register={register}
182+
checked
183+
readOnly
184+
/>
185+
</div>
186+
<div className="w-full p-2">
187+
<button className="flex px-4 py-2 mx-auto font-bold bg-white border border-gray-400 border-solid rounded hover:bg-gray-400">
188+
BESTILL
189+
</button>
190+
</div>
118191
</div>
119192
</div>
120193
</div>
121-
</div>
194+
</form>
122195
</section>
123196
</>
124197
);

0 commit comments

Comments
 (0)