Skip to content

Commit 6e702f3

Browse files
committed
fix(checkout): complete form + order summary; use items/cartTotal/formatCurrency and submitting state
1 parent db59ad1 commit 6e702f3

1 file changed

Lines changed: 169 additions & 17 deletions

File tree

src/component/Checkout.jsx

Lines changed: 169 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ const Checkout = () => {
7272
const e = {};
7373
if (!form.firstName.trim()) e.firstName = "Required";
7474
if (!form.lastName.trim()) e.lastName = "Required";
75-
if (!form.email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/))
76-
e.email = "Enter a valid email";
75+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) e.email = "Enter a valid email";
7776
if (!form.address1.trim()) e.address1 = "Required";
7877
if (!form.city.trim()) e.city = "Required";
7978
if (!form.zip.trim()) e.zip = "Required";
@@ -90,7 +89,8 @@ const Checkout = () => {
9089

9190
try {
9291
setSubmitting(true);
93-
await new Promise((r) => setTimeout(r, 600)); // demo delay
92+
// Demo delay / here you'd call your API or payment provider
93+
await new Promise((r) => setTimeout(r, 600));
9494
emptyCart();
9595
navigate("/exit");
9696
} finally {
@@ -99,7 +99,7 @@ const Checkout = () => {
9999
}
100100

101101
return (
102-
<div className="mx-auto max-w-7xl">
102+
<div className="mx-auto max-w-7xl p-4">
103103
<h1 className="mb-6 font-display text-3xl font-semibold text-ink">
104104
Checkout
105105
</h1>
@@ -128,17 +128,12 @@ const Checkout = () => {
128128
value={form.firstName}
129129
onChange={handleChange}
130130
autoComplete="given-name"
131-
aria-describedby={
132-
errors.firstName ? "firstName-error" : undefined
133-
}
131+
aria-describedby={errors.firstName ? "firstName-error" : undefined}
134132
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
135133
required
136134
/>
137135
{errors.firstName && (
138-
<p
139-
id="firstName-error"
140-
className="mt-1 text-xs text-danger"
141-
>
136+
<p id="firstName-error" className="mt-1 text-xs text-danger">
142137
{errors.firstName}
143138
</p>
144139
)}
@@ -152,9 +147,7 @@ const Checkout = () => {
152147
value={form.lastName}
153148
onChange={handleChange}
154149
autoComplete="family-name"
155-
aria-describedby={
156-
errors.lastName ? "lastName-error" : undefined
157-
}
150+
aria-describedby={errors.lastName ? "lastName-error" : undefined}
158151
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
159152
required
160153
/>
@@ -201,12 +194,171 @@ const Checkout = () => {
201194
</section>
202195

203196
{/* Shipping address */}
204-
{/* (kept as-is from your version — unchanged) */}
205-
{/* ... */}
197+
<section className="rounded-2xl border border-neutral-200 bg-white p-6 shadow-card">
198+
<h2 className="font-display text-lg font-semibold text-ink">
199+
Shipping address
200+
</h2>
201+
<div className="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
202+
{/* Address 1 */}
203+
<label className="block sm:col-span-2">
204+
<span className="text-sm font-medium">Address line 1</span>
205+
<input
206+
name="address1"
207+
value={form.address1}
208+
onChange={handleChange}
209+
autoComplete="address-line1"
210+
aria-describedby={errors.address1 ? "address1-error" : undefined}
211+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
212+
required
213+
/>
214+
{errors.address1 && (
215+
<p id="address1-error" className="mt-1 text-xs text-danger">
216+
{errors.address1}
217+
</p>
218+
)}
219+
</label>
220+
221+
{/* Address 2 */}
222+
<label className="block sm:col-span-2">
223+
<span className="text-sm font-medium">Address line 2 (optional)</span>
224+
<input
225+
name="address2"
226+
value={form.address2}
227+
onChange={handleChange}
228+
autoComplete="address-line2"
229+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
230+
/>
231+
</label>
232+
233+
{/* City */}
234+
<label className="block">
235+
<span className="text-sm font-medium">City</span>
236+
<input
237+
name="city"
238+
value={form.city}
239+
onChange={handleChange}
240+
autoComplete="address-level2"
241+
aria-describedby={errors.city ? "city-error" : undefined}
242+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
243+
required
244+
/>
245+
{errors.city && (
246+
<p id="city-error" className="mt-1 text-xs text-danger">
247+
{errors.city}
248+
</p>
249+
)}
250+
</label>
251+
252+
{/* State/Region */}
253+
<label className="block">
254+
<span className="text-sm font-medium">State/Region</span>
255+
<input
256+
name="state"
257+
value={form.state}
258+
onChange={handleChange}
259+
autoComplete="address-level1"
260+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
261+
/>
262+
</label>
263+
264+
{/* ZIP */}
265+
<label className="block">
266+
<span className="text-sm font-medium">ZIP / Postal code</span>
267+
<input
268+
name="zip"
269+
value={form.zip}
270+
onChange={handleChange}
271+
autoComplete="postal-code"
272+
aria-describedby={errors.zip ? "zip-error" : undefined}
273+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
274+
required
275+
/>
276+
{errors.zip && (
277+
<p id="zip-error" className="mt-1 text-xs text-danger">
278+
{errors.zip}
279+
</p>
280+
)}
281+
</label>
282+
283+
{/* Country */}
284+
<label className="block">
285+
<span className="text-sm font-medium">Country</span>
286+
<select
287+
name="country"
288+
value={form.country}
289+
onChange={handleChange}
290+
aria-describedby={errors.country ? "country-error" : undefined}
291+
className="mt-1 block w-full rounded-xl border-neutral-300 focus:border-primary focus:ring-primary"
292+
required
293+
>
294+
<option value="">Select…</option>
295+
<option value="GR">Greece</option>
296+
<option value="US">United States</option>
297+
<option value="GB">United Kingdom</option>
298+
<option value="DE">Germany</option>
299+
<option value="FR">France</option>
300+
<option value="ES">Spain</option>
301+
<option value="IT">Italy</option>
302+
{/* add more as needed */}
303+
</select>
304+
{errors.country && (
305+
<p id="country-error" className="mt-1 text-xs text-danger">
306+
{errors.country}
307+
</p>
308+
)}
309+
</label>
310+
311+
{/* Terms */}
312+
<label className="mt-2 flex items-center gap-2 sm:col-span-2">
313+
<input
314+
type="checkbox"
315+
name="agree"
316+
checked={form.agree}
317+
onChange={handleChange}
318+
className="h-4 w-4 rounded border-neutral-300 text-primary focus:ring-primary"
319+
/>
320+
<span className="text-sm text-neutral-700">
321+
I agree to the terms and conditions
322+
</span>
323+
</label>
324+
{errors.agree && (
325+
<p className="text-xs text-danger sm:col-span-2">{errors.agree}</p>
326+
)}
327+
</div>
328+
</section>
329+
330+
<button
331+
type="submit"
332+
disabled={submitting}
333+
className="mt-2 inline-flex items-center justify-center rounded-xl bg-ink px-5 py-3 text-white shadow-card disabled:opacity-60 hover:bg-neutral-900"
334+
>
335+
{submitting ? "Processing…" : "Place order"}
336+
</button>
206337
</form>
207338

208339
{/* Order summary */}
209-
{/* (also unchanged — just as in your version) */}
340+
<aside className="h-fit rounded-2xl border border-neutral-200 bg-white p-6 shadow-card">
341+
<h2 className="mb-3 font-display text-lg font-semibold text-ink">
342+
Order summary
343+
</h2>
344+
<ul className="divide-y">
345+
{items.map((it) => (
346+
<li key={it.id} className="py-3 flex items-start justify-between">
347+
<div className="mr-4">
348+
<div className="font-medium">{it.name}</div>
349+
<div className="text-sm text-neutral-600">Qty: {it.quantity}</div>
350+
</div>
351+
<div className="text-right font-medium">
352+
{formatCurrency((it.price || 0) * (it.quantity || 0))}
353+
</div>
354+
</li>
355+
))}
356+
</ul>
357+
<div className="mt-4 flex items-center justify-between text-base font-semibold">
358+
<span>Total</span>
359+
<span>{formatCurrency(cartTotal || 0)}</span>
360+
</div>
361+
</aside>
210362
</div>
211363
</div>
212364
);

0 commit comments

Comments
 (0)