@@ -25,27 +25,26 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
2525 const makeKey = ( { card } ) =>
2626 `${ card ?. productName } |${ card ?. setName } |${ card ?. number } |${ card ?. printing } ` ;
2727
28- // 1. Precompute stable unique IDs including duplicate counts for all items in matchedCardData
28+ // Stable unique IDs including duplicate counts
2929 const itemUniqueIds = useMemo ( ( ) => {
3030 const counts = { } ;
3131 return matchedCardData . map ( ( item ) => {
3232 const baseKey = makeKey ( item ) ;
3333 counts [ baseKey ] = ( counts [ baseKey ] || 0 ) + 1 ;
34- return `${ baseKey } |${ counts [ baseKey ] } ` ; // e.g. "card|set|num|print|1", "card|set|num|print|2"
34+ return `${ baseKey } |${ counts [ baseKey ] } ` ;
3535 } ) ;
3636 } , [ matchedCardData ] ) ;
3737
38- // 2. Sort matchedCardData with original index retained for referencing unique IDs
38+ // Sorted data with index
3939 const sortedDataWithIndex = useMemo ( ( ) => {
4040 if ( ! Array . isArray ( matchedCardData ) ) return [ ] ;
41-
4241 const sorted = [ ...matchedCardData ] . map ( ( item , index ) => ( { item, originalIndex : index } ) ) ;
4342 sorted . sort ( ( a , b ) => {
4443 const aValue = sortConfig . key === 'marketPrice'
45- ? a . item . data ?. marketPrice || 0
44+ ? parseFloat ( a . item . data ?. marketPrice ) || 0
4645 : a . item . card [ sortConfig . key ] ;
4746 const bValue = sortConfig . key === 'marketPrice'
48- ? b . item . data ?. marketPrice || 0
47+ ? parseFloat ( b . item . data ?. marketPrice ) || 0
4948 : b . item . card [ sortConfig . key ] ;
5049 if ( aValue < bValue ) return sortConfig . direction === 'ascending' ? - 1 : 1 ;
5150 if ( aValue > bValue ) return sortConfig . direction === 'ascending' ? 1 : - 1 ;
@@ -54,15 +53,14 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
5453 return sorted ;
5554 } , [ matchedCardData , sortConfig ] ) ;
5655
57- // 3. Pagination slice on sorted data
56+ // Pagination slice
5857 const sortedAndPaginatedData = useMemo ( ( ) => {
5958 const indexOfLast = currentPage * itemsPerPage ;
6059 const indexOfFirst = indexOfLast - itemsPerPage ;
6160 const currentItems = sortedDataWithIndex . slice ( indexOfFirst , indexOfLast ) ;
6261 return { currentItems, totalCount : matchedCardData . length } ;
6362 } , [ sortedDataWithIndex , currentPage , matchedCardData . length ] ) ;
6463
65- // Unique IDs in sorted order (full dataset)
6664 const sortedUniqueIds = useMemo (
6765 ( ) => sortedDataWithIndex . map ( ( { originalIndex } ) => itemUniqueIds [ originalIndex ] ) ,
6866 [ sortedDataWithIndex , itemUniqueIds ]
@@ -77,7 +75,6 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
7775 if ( isShift && lastCheckedKey !== null && sortedUniqueIds . length ) {
7876 const start = sortedUniqueIds . indexOf ( lastCheckedKey ) ;
7977 const end = sortedUniqueIds . indexOf ( uniqueId ) ;
80-
8178 if ( start !== - 1 && end !== - 1 ) {
8279 const [ lo , hi ] = start < end ? [ start , end ] : [ end , start ] ;
8380 for ( let i = lo ; i <= hi ; i ++ ) {
@@ -96,8 +93,6 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
9693 [ selectedKeys , lastCheckedKey , sortedUniqueIds ]
9794 ) ;
9895
99-
100- // Current page unique IDs
10196 const pagedUniqueIds = useMemo (
10297 ( ) => sortedAndPaginatedData . currentItems . map ( ( { originalIndex } ) => itemUniqueIds [ originalIndex ] ) ,
10398 [ sortedAndPaginatedData , itemUniqueIds ]
@@ -127,7 +122,6 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
127122 setSelectAllChecked ( false ) ;
128123 } ;
129124
130- // Sort handler unchanged
131125 const handleSort = useCallback (
132126 ( key ) => {
133127 setSortConfig ( ( prev ) => {
@@ -142,19 +136,18 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
142136 [ ]
143137 ) ;
144138
145- // Add to collection logic unchanged except use uniqueId filtering
146139 const addToCollection = useCallback ( async ( ) => {
147140 if ( selectedKeys . size === 0 ) {
148- return setNotification ( { show : true , message : 'No cards were selected to add to the collection!' } ) ;
149- }
150- const token = localStorage . getItem ( "token" ) ;
151- if ( ! token ) {
152- setNotification ( { show : true , message : "You must be logged in to add cards." } ) ;
153- return ;
141+ return setNotification ( {
142+ show : true ,
143+ message : "No cards were selected to add to the collection!" ,
144+ } ) ;
154145 }
146+
155147 const selectedData = matchedCardData . filter ( ( _ , index ) =>
156148 selectedKeys . has ( itemUniqueIds [ index ] )
157149 ) ;
150+
158151 const collectionArray = selectedData . map ( ( { card, data } ) => ( {
159152 productName : card ?. productName ,
160153 setName : card ?. setName ,
@@ -166,23 +159,31 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
166159 lowPrice : data ?. lowPrice ,
167160 quantity : 1 ,
168161 } ) ) ;
162+
169163 try {
170164 const response = await fetch ( `/api/Yugioh/cards` , {
171- method : 'POST' ,
165+ method : "POST" ,
166+ credentials : "include" , // ✅ automatically sends the JWT cookie
172167 headers : {
173168 "Content-Type" : "application/json" ,
174- Authorization : `Bearer ${ token } ` ,
175169 } ,
176170 body : JSON . stringify ( { cards : collectionArray } ) ,
177171 } ) ;
172+
178173 if ( ! response . ok ) throw new Error ( ) ;
179- setNotification ( { show : true , message : 'Card(s) added to the collection!' } ) ;
174+ setNotification ( {
175+ show : true ,
176+ message : "Card(s) added to the collection!" ,
177+ } ) ;
180178 } catch {
181- setNotification ( { show : true , message : 'Card(s) failed to save!' } ) ;
179+ setNotification ( {
180+ show : true ,
181+ message : "Card(s) failed to save!" ,
182+ } ) ;
182183 }
183184 } , [ selectedKeys , matchedCardData , itemUniqueIds ] ) ;
184185
185- // Download CSV using uniqueIds filtering
186+
186187 const downloadCSV = useCallback ( ( ) => {
187188 if ( selectedKeys . size === 0 ) {
188189 setNotification ( { show : true , message : 'No cards selected to download!' } ) ;
@@ -212,12 +213,18 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
212213 link . click ( ) ;
213214 document . body . removeChild ( link ) ;
214215 URL . revokeObjectURL ( url ) ;
215- } , [ selectedKeys , matchedCardData , itemUniqueIds ] ) ;
216+ } , [ selectedKeys , matchedCardData , setMatchedCardData , itemUniqueIds ] ) ;
216217
217218 const handleGoToCollectionPage = useCallback ( ( ) => {
218219 router . push ( '/yugioh/my-collection' ) ;
219220 } , [ router ] ) ;
220221
222+ // Format helper for prices
223+ const formatPrice = ( val ) => {
224+ const num = parseFloat ( val ) ;
225+ return isNaN ( num ) ? "0.00" : `${ num . toFixed ( 2 ) } ` ;
226+ } ;
227+
221228 return (
222229 < div className = "mx-auto w-full mb-10 min-h-fit" >
223230 < Notification
@@ -241,7 +248,6 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
241248
242249 { /* Table */ }
243250 < div className = "w-full mx-auto overflow-x-auto" >
244- { /* Bulk Action Bar */ }
245251 { selectedKeys . size > 0 && (
246252 < div className = "my-5 py-2 h-fit bg-stone-500 bg-opacity-20 backdrop-blur backdrop-filter text-white p-2 mb-2 flex justify-between items-center" >
247253 < div className = "text-sm float-start" >
@@ -324,10 +330,10 @@ const YugiohCardDataTable = ( { matchedCardData, setMatchedCardData } ) => {
324330 { card ?. condition || 'N/A' }
325331 </ td >
326332 < td className = "p-2 text-center border-t border-gray-100 text-xs lg:text-sm sm:text-left text-black hover:bg-black hover:text-white" >
327- { data ?. marketPrice ?? 'N/A' }
333+ { formatPrice ( data ?. marketPrice ) }
328334 </ td >
329335 < td className = "p-2 text-center border-t border-gray-100 text-xs lg:text-sm sm:text-left text-black hover:bg-black hover:text-white" >
330- { data ?. lowPrice ?? 'N/A' }
336+ { formatPrice ( data ?. lowPrice ) }
331337 </ td >
332338 </ tr >
333339 ) ;
0 commit comments