@@ -22,6 +22,20 @@ import Link from 'next/link';
2222import { useRouter } from 'next/navigation' ;
2323import Image from 'next/image' ;
2424
25+ type shippingType = 'standard' | 'express' ;
26+
27+ interface shippingDetails {
28+ name : string ;
29+ price : number ;
30+ duration : string ;
31+ }
32+
33+ // logic usually done in the backend, client calls the exposed endopoint
34+ const shippingMethods : Record < shippingType , shippingDetails > = {
35+ standard : { name : 'Standard Shipping' , price : 25 , duration : '5-7 business days' } ,
36+ express : { name : 'Express Shipping' , price : 50 , duration : '2-3 business days' } ,
37+ } ;
38+
2539interface CheckoutFormData {
2640 // Contact Information
2741 email : string ;
@@ -37,6 +51,8 @@ interface CheckoutFormData {
3751 zipCode : string ;
3852 country : string ;
3953
54+ shippingMethod : shippingType ;
55+
4056 // Payment Information
4157 paymentMethod : string ;
4258 cardNumber : string ;
@@ -67,6 +83,7 @@ export default function CheckoutPage() {
6783 city : '' ,
6884 state : '' ,
6985 zipCode : '' ,
86+ shippingMethod : 'standard' ,
7087 country : 'US' ,
7188 paymentMethod : 'card' ,
7289 cardNumber : '' ,
@@ -84,14 +101,16 @@ export default function CheckoutPage() {
84101
85102 const subtotal = total ;
86103 const discount = subtotal * 0.1 ;
87- const deliveryFee = 50 ;
104+ const deliveryFee = shippingMethods [ formData . shippingMethod ] . price ;
88105 const tax = ( subtotal - discount ) * 0.08 ;
89106 const finalTotal = subtotal - discount + deliveryFee + tax ;
90107
91108 const handleInputChange = ( field : keyof CheckoutFormData , value : string | boolean ) => {
92109 setFormData ( ( prev ) => ( { ...prev , [ field ] : value } ) ) ;
93110 } ;
94111
112+ console . log ( formData . shippingMethod ) ;
113+
95114 const handleSubmit = async ( e : React . FormEvent ) => {
96115 e . preventDefault ( ) ;
97116 setIsProcessing ( true ) ;
@@ -218,7 +237,7 @@ export default function CheckoutPage() {
218237 </ div >
219238
220239 < div >
221- < Label htmlFor = "address" > Address *</ Label >
240+ < Label htmlFor = "address" > Street Address *</ Label >
222241 < Input
223242 id = "address"
224243 required
@@ -239,23 +258,30 @@ export default function CheckoutPage() {
239258 </ div >
240259
241260 < div className = "grid grid-cols-1 md:grid-cols-3 gap-4" >
242- < div >
243- < Label htmlFor = "city" > City *</ Label >
244- < Input
245- id = "city"
246- required
247- value = { formData . city }
248- onChange = { ( e ) => handleInputChange ( 'city' , e . target . value ) }
249- placeholder = "New York"
250- />
251- </ div >
261+ { /* <div>
262+ <Label htmlFor="state">States *</Label>
263+ <Select
264+ value={formData.state}
265+ onValueChange={(value) => handleInputChange('state', value)}
266+ >
267+ <SelectTrigger aria-labelledby="state-label">
268+ <SelectValue placeholder="Select state" />
269+ </SelectTrigger>
270+ <SelectContent>
271+ <SelectItem value="NY">New York</SelectItem>
272+ <SelectItem value="CA">California</SelectItem>
273+ <SelectItem value="TX">Texas</SelectItem>
274+ <SelectItem value="FL">Florida</SelectItem>
275+ </SelectContent>
276+ </Select>
277+ </div> */ }
252278 < div >
253279 < Label htmlFor = "state" > State *</ Label >
254280 < Select
255281 value = { formData . state }
256282 onValueChange = { ( value ) => handleInputChange ( 'state' , value ) }
257283 >
258- < SelectTrigger >
284+ < SelectTrigger aria-label = "state" >
259285 < SelectValue placeholder = "Select state" />
260286 </ SelectTrigger >
261287 < SelectContent >
@@ -266,6 +292,16 @@ export default function CheckoutPage() {
266292 </ SelectContent >
267293 </ Select >
268294 </ div >
295+ < div >
296+ < Label htmlFor = "city" > City *</ Label >
297+ < Input
298+ id = "city"
299+ required
300+ value = { formData . city }
301+ onChange = { ( e ) => handleInputChange ( 'city' , e . target . value ) }
302+ placeholder = "New York"
303+ />
304+ </ div >
269305 < div >
270306 < Label htmlFor = "zipCode" > ZIP Code *</ Label >
271307 < Input
@@ -283,43 +319,38 @@ export default function CheckoutPage() {
283319 { /* Shipping Method */ }
284320 < div className = "bg-white rounded-2xl p-6" >
285321 < h2 className = "text-xl font-semibold text-gray-900 mb-6" > Shipping Method</ h2 >
286- < RadioGroup defaultValue = "standard" className = "space-y-4" >
287- < div className = "flex items-center space-x-3 p-4 border border-gray-200 rounded-lg" >
288- < RadioGroupItem value = "standard" id = "standard" />
289- < div className = "flex-1" >
290- < Label
291- htmlFor = "standard"
292- className = "flex items-center justify-between cursor-pointer"
293- >
294- < div className = "flex items-center" >
295- < Truck className = "h-5 w-5 mr-3 text-gray-600" />
296- < div >
297- < div className = "font-medium" > Standard Shipping</ div >
298- < div className = "text-sm text-gray-600" > 5-7 business days</ div >
299- </ div >
300- </ div >
301- < span className = "font-medium" > $50.00</ span >
302- </ Label >
303- </ div >
304- </ div >
305- < div className = "flex items-center space-x-3 p-4 border border-gray-200 rounded-lg" >
306- < RadioGroupItem value = "express" id = "express" />
307- < div className = "flex-1" >
308- < Label
309- htmlFor = "express"
310- className = "flex items-center justify-between cursor-pointer"
311- >
312- < div className = "flex items-center" >
313- < Truck className = "h-5 w-5 mr-3 text-gray-600" />
314- < div >
315- < div className = "font-medium" > Express Shipping</ div >
316- < div className = "text-sm text-gray-600" > 2-3 business days</ div >
322+ < RadioGroup
323+ value = { formData . shippingMethod }
324+ onValueChange = { ( value ) =>
325+ handleInputChange ( 'shippingMethod' , value as shippingType )
326+ }
327+ className = "space-y-4"
328+ >
329+ { Object . entries ( shippingMethods ) . map ( ( [ key , details ] ) => (
330+ < div
331+ key = { key }
332+ className = "flex items-center space-x-3 p-4 border border-gray-200 rounded-lg"
333+ >
334+ < RadioGroupItem value = { key } id = { key } />
335+ < div className = "flex-1" >
336+ < Label
337+ htmlFor = { key }
338+ className = "flex items-center justify-between cursor-pointer"
339+ >
340+ < div className = "flex items-center" >
341+ < Truck className = "h-5 w-5 mr-3 text-gray-600" />
342+ < div >
343+ < div className = "font-medium" > { details . name } </ div >
344+ < div className = "text-sm text-gray-600" >
345+ { key === 'standard' ? '5-7 business days' : '2-3 business days' }
346+ </ div >
347+ </ div >
317348 </ div >
318- </ div >
319- < span className = "font-medium" > $25.00 </ span >
320- </ Label >
349+ < span className = "font-medium" > $ { details . price . toFixed ( 2 ) } </ span >
350+ </ Label >
351+ </ div >
321352 </ div >
322- </ div >
353+ ) ) }
323354 </ RadioGroup >
324355 </ div >
325356
0 commit comments