1+ "use client"
2+
3+ import type React from "react"
4+ import { useState , useEffect , useRef } from "react"
5+ import { Trash2 , ChevronDown } from "lucide-react"
6+ import { useNavigate } from "react-router-dom"
7+
8+ interface CartItem {
9+ id : string
10+ name : string
11+ price : string
12+ quantity : number
13+ size ?: string
14+ image ?: string
15+ }
16+
17+ interface CartCheckoutItemListProps {
18+ items : CartItem [ ]
19+ onRemoveItem ?: ( itemId : string ) => void
20+ onUpdateQuantity ?: ( itemId : string , quantity : number ) => void
21+ }
22+
23+ export default function CartCheckoutItemList ( { items, onRemoveItem, onUpdateQuantity } : CartCheckoutItemListProps ) {
24+ const navigate = useNavigate ( )
25+ const [ showScrollIndicator , setShowScrollIndicator ] = useState ( false )
26+ const scrollContainerRef = useRef < HTMLDivElement > ( null )
27+
28+ const handleItemClick = ( itemName : string ) => {
29+ // Format the item name for URL (same pattern as ProductCard)
30+ const formattedName = encodeURIComponent ( itemName . toLowerCase ( ) . replace ( / \s + / g, "-" ) )
31+ navigate ( `/shop/item/${ formattedName } ` )
32+ }
33+
34+ const handleRemoveItem = ( e : React . MouseEvent , itemId : string ) => {
35+ e . stopPropagation ( ) // Prevent item click when deleting
36+ onRemoveItem ?.( itemId )
37+ }
38+
39+ const handleQuantityChange = ( e : React . ChangeEvent < HTMLSelectElement > , itemId : string ) => {
40+ e . stopPropagation ( )
41+ const newQuantity = Number . parseInt ( e . target . value )
42+ onUpdateQuantity ?.( itemId , newQuantity )
43+ }
44+
45+ const checkScrollPosition = ( ) => {
46+ const container = scrollContainerRef . current
47+ if ( ! container ) return
48+
49+ const { scrollTop, scrollHeight, clientHeight } = container
50+ const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10 // 10px threshold
51+ const hasScrollableContent = scrollHeight > clientHeight
52+
53+ setShowScrollIndicator ( hasScrollableContent && ! isAtBottom )
54+ }
55+
56+ useEffect ( ( ) => {
57+ const container = scrollContainerRef . current
58+ if ( ! container ) return
59+
60+ // Check initial scroll position
61+ checkScrollPosition ( )
62+
63+ // Add scroll event listener
64+ container . addEventListener ( "scroll" , checkScrollPosition )
65+
66+ // Check when items change (in case items are added/removed)
67+ const resizeObserver = new ResizeObserver ( checkScrollPosition )
68+ resizeObserver . observe ( container )
69+
70+ return ( ) => {
71+ container . removeEventListener ( "scroll" , checkScrollPosition )
72+ resizeObserver . disconnect ( )
73+ }
74+ } , [ items ] )
75+
76+ return (
77+ < div className = "relative" >
78+ { /* Scrollable Container */ }
79+ < div ref = { scrollContainerRef } className = "space-y-4 overflow-y-auto" style = { { maxHeight : "550px" } } >
80+ { items . map ( ( item ) => (
81+ < div
82+ key = { item . id }
83+ className = "flex gap-4 p-4 border border-gray-700 rounded-lg hover:bg-gray-800/50 transition-colors cursor-pointer"
84+ onClick = { ( ) => handleItemClick ( item . name ) }
85+ >
86+ { /* Product Image */ }
87+ < div className = "w-25 h-25 bg-gray-600 rounded-md flex-shrink-0" >
88+ { item . image ? (
89+ < img
90+ src = { item . image || "/placeholder.svg?height=80&width=80" }
91+ alt = { item . name }
92+ className = "w-full h-full object-cover rounded-md"
93+ />
94+ ) : (
95+ < div className = "w-full h-full bg-gray-600 rounded-md" />
96+ ) }
97+ </ div >
98+
99+ { /* Product Details */ }
100+ < div className = "flex-1 min-w-0 flex flex-col justify-between" >
101+ < div className = "flex justify-between items-center pt-1" >
102+ < h3 className = "font-semibold text-white text-xl truncate" > { item . name } </ h3 >
103+ { /* Delete Button */ }
104+ < button
105+ onClick = { ( e ) => handleRemoveItem ( e , item . id ) }
106+ className = "p-2 text-gray-400 hover:text-red-400 hover:bg-gray-700 rounded-md transition-colors"
107+ aria-label = "Remove item"
108+ >
109+ < Trash2 size = { 20 } />
110+ </ button >
111+ </ div >
112+
113+ { item . size && < p className = "text-gray-400 text-sm" > Size: { item . size } </ p > }
114+
115+ < div className = "flex justify-between" >
116+
117+ { /* Quantity Selector */ }
118+ < div className = "pb-1" >
119+ < label className = "text-gray-400 text-sm mr-2" > Qty:</ label >
120+ < select
121+ value = { item . quantity }
122+ onChange = { ( e ) => handleQuantityChange ( e , item . id ) }
123+ className = "bg-gray-800 border border-gray-700 rounded px-2 py-1 text-white text-sm"
124+ onClick = { ( e ) => e . stopPropagation ( ) }
125+ >
126+ { [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] . map ( ( num ) => (
127+ < option key = { num } value = { num } >
128+ { num }
129+ </ option >
130+ ) ) }
131+ </ select >
132+ </ div >
133+ < div className = "text-right" > { /* mt-auto pushes to bottom */ }
134+ < p className = "text-lg" > { item . price } </ p >
135+ </ div >
136+ </ div >
137+ </ div >
138+ </ div >
139+ ) ) }
140+
141+ { items . length === 0 && (
142+ < div className = "text-center py-12 text-gray-400" >
143+ < p className = "text-lg" > Your cart is empty</ p >
144+ < p className = "text-sm mt-2" > Add some items to get started!</ p >
145+ </ div >
146+ ) }
147+ </ div >
148+
149+ { /* Scroll Down Indicator */ }
150+ { showScrollIndicator && (
151+ < div className = "absolute bottom-0 left-0 right-0 flex justify-center" >
152+ < div className = "bg-gradient-to-t from-gray-900 via-gray-900/80 to-transparent pt-8 pb-2 px-4" >
153+ < div className = "flex items-center gap-2 text-gray-400 text-sm animate-bounce" >
154+ < ChevronDown size = { 16 } />
155+ < span > Scroll down for more items</ span >
156+ < ChevronDown size = { 16 } />
157+ </ div >
158+ </ div >
159+ </ div >
160+ ) }
161+ </ div >
162+ )
163+ }
0 commit comments