@@ -49,6 +49,7 @@ import { usePurchaseAmounts } from "./page-components/usePurchaseAmounts";
4949import { ActionCell } from "./page-components/ActionCell" ;
5050import { StatusCell } from "./page-components/StatusCell" ;
5151import { PurchaseIdCell } from "./page-components/PurchaseIdCell" ;
52+ import { usePurchaseTableColumns } from "./page-components/purchaseTableColumns" ;
5253
5354/**
5455 * Main page of the application displaying purchase data in a tabular format
@@ -149,34 +150,6 @@ export default function IndexPage() {
149150 setRefreshTrigger ( ( prev ) => prev + 1 ) ;
150151 } ;
151152
152- /**
153- * Renders the action column for a purchase row based on its status
154- *
155- * The available actions depend on the purchase status:
156- * - If refunded, displays a "Refunded" label
157- * - If no feedback, shows "Create Feedback" button
158- * - If has feedback but no publication, shows "Publish Feedback" button
159- * - If has feedback and publication, shows "Refund" button
160- *
161- * @param {Object } item - The purchase item data
162- * @param {string } item.purchase - Purchase ID
163- * @param {boolean } item.refunded - Whether the purchase has been refunded
164- * @param {boolean } item.hasFeedback - Whether the purchase has feedback
165- * @param {boolean } item.hasPublication - Whether the feedback has been published
166- * @param {number } item.amount - The purchase amount
167- * @returns {JSX.Element } The rendered action column content
168- */
169- const renderActionColumn = ( item : PurchaseStatus ) => (
170- < ActionCell
171- item = { item }
172- hasWritePermission = { hasWritePermission }
173- onCreateFeedback = { handleCreateFeedback }
174- onReturnItem = { handleReturnItem }
175- onPublishFeedback = { handlePublishFeedback }
176- onRefundPurchase = { handleRefundPurchases }
177- />
178- ) ;
179-
180153 /**
181154 * Handles opening the return modal for a specific purchase
182155 * Show a confirmation Modal to confirm the return
@@ -240,6 +213,19 @@ export default function IndexPage() {
240213 setGeneratePublicLink ( true ) ;
241214 } ;
242215
216+ // Use custom hook for table columns configuration
217+ const { columns, emptyContent } = usePurchaseTableColumns ( {
218+ hasWritePermission,
219+ onCreateFeedback : handleCreateFeedback ,
220+ onReturnItem : handleReturnItem ,
221+ onPublishFeedback : handlePublishFeedback ,
222+ onRefundPurchase : handleRefundPurchases ,
223+ onEditPurchase : handleEditPurchase ,
224+ onGenerateLink : handleGenerateLink ,
225+ onSetScreenshot : setScreenshot ,
226+ onCreateNewPurchase : ( ) => setCreateNewPurchase ( true ) ,
227+ } ) ;
228+
243229 return (
244230 < DefaultLayout >
245231 < section
@@ -257,138 +243,7 @@ export default function IndexPage() {
257243 ) : (
258244 < div className = "flex gap-3 max-w-screen" >
259245 < PaginatedTable
260- columns = { [
261- {
262- field : "purchase" ,
263- label : t ( "purchase" ) ,
264- sortable : false ,
265- cellCopyable : true ,
266- className : "hidden md:table-cell" ,
267- headerClassName : "hidden md:table-cell" ,
268- render : ( item : PurchaseStatus ) => (
269- < PurchaseIdCell
270- purchaseId = { item . purchase }
271- hasPublication = { item . hasPublication }
272- onEditPurchase = { handleEditPurchase }
273- onGenerateLink = { handleGenerateLink }
274- />
275- ) ,
276- } ,
277- {
278- field : "date" ,
279- label : t ( "date" ) ,
280- sortable : true ,
281- className : "hidden md:table-cell" ,
282- headerClassName : "hidden md:table-cell" ,
283- } ,
284- {
285- field : "order" ,
286- label : t ( "order" ) ,
287- sortable : true ,
288- className : "hidden md:table-cell" ,
289- headerClassName : "hidden md:table-cell" ,
290- render : ( item : PurchaseStatus ) => {
291- return (
292- < >
293- < Link
294- className = "text-blue-500 hover:underline break-keep"
295- target = "_blank"
296- to = { `${ import . meta. env . AMAZON_BASE_URL } ${ item . order } ` }
297- >
298- { cleanAmazonOrderNumber ( item . order ) }
299- </ Link >
300- < CopyButton
301- className = "absolute top-0 right-0"
302- value = { item . order }
303- />
304- </ >
305- ) ;
306- } ,
307- } ,
308- {
309- field : "description" ,
310- label : t ( "description" ) ,
311- sortable : false ,
312- render : ( item : PurchaseStatus ) => (
313- < StatusCell
314- text = { item . description }
315- screenshot = { item . purchaseScreenshot }
316- screenshotSummary = { item . screenshotSummary }
317- copyTooltipKey = "copy-screenshots"
318- onScreenshotClick = { setScreenshot }
319- />
320- ) ,
321- onCellAction : ( item : PurchaseStatus ) => {
322- item . screenshotSummary
323- ? setScreenshot ( [
324- item . purchaseScreenshot || Transparent1x1WebpPixel ,
325- item . screenshotSummary ,
326- ] )
327- : setScreenshot ( item . purchaseScreenshot || Transparent1x1WebpPixel ) ;
328- } ,
329- } ,
330- {
331- field : "amount" ,
332- label : t ( "amount" ) ,
333- sortable : false ,
334- className : "hidden md:table-cell" ,
335- headerClassName : "hidden md:table-cell" ,
336- } ,
337- {
338- field : "hasFeedback" ,
339- label : t ( "hasFeedback" ) ,
340- sortable : false ,
341- className : "hidden md:table-cell" ,
342- headerClassName : "hidden md:table-cell" ,
343- } ,
344- {
345- field : "hasPublication" ,
346- label : t ( "hasPublication" ) ,
347- sortable : false ,
348- className : "hidden md:table-cell" ,
349- headerClassName : "hidden md:table-cell" ,
350- render : ( item : PurchaseStatus ) => (
351- < StatusCell
352- text = { item . hasPublication ? t ( "yes" ) : t ( "no" ) }
353- screenshot = { item . publicationScreenshot }
354- copyTooltipKey = "copy-screenshot"
355- onScreenshotClick = { ( screenshot ) => setScreenshot ( screenshot ) }
356- />
357- ) ,
358- onCellAction : ( item ) => {
359- if ( item . hasPublication ) {
360- setScreenshot ( item . publicationScreenshot ) ;
361- }
362- } ,
363- } ,
364- {
365- field : "refunded" ,
366- label : t ( "refunded" ) ,
367- sortable : false ,
368- className : "hidden md:table-cell" ,
369- headerClassName : "hidden md:table-cell" ,
370- render : ( item : PurchaseStatus ) => {
371- return item . refunded ? (
372- < >
373- { item . transactionId && item . transactionId . length >= 4 && ! item . transactionId . startsWith ( "REFUND_" ) ? (
374- < Link
375- className = "text-blue-500 hover:underline break-keep"
376- target = "_blank"
377- to = { `${ import . meta. env . PAYPAL_TRANSACTION_BASE_URL } ${ item . transactionId } ` } > { t ( "yes" ) }
378- </ Link >
379- ) : (
380- < span > { t ( "yes" ) } </ span >
381- ) }
382- </ > ) :
383- < > { t ( "no" ) } </ > ;
384- }
385- } ,
386- {
387- field : "actions" ,
388- label : t ( "actions" ) ,
389- render : ( item ) => renderActionColumn ( item ) ,
390- } ,
391- ] }
246+ columns = { columns }
392247 dataUrl = { `${ import . meta. env . API_BASE_URL } /purchase-status?limitToNotRefunded=${ toggleAllPurchases ? "false" : "true" } ` }
393248 manualData = { searchResults . length > 0 ? searchData : undefined }
394249 manualIsLoading = { searchDataLoading }
@@ -399,22 +254,7 @@ export default function IndexPage() {
399254 refreshTrigger = { refreshTrigger }
400255 rowKey = "purchase"
401256 title = { getTitleComponent }
402- emptyContent = {
403- < div className = "text-center text-muted-foreground p-4" >
404- { t ( "no-data-available" ) }
405- { hasWritePermission && (
406- < div className = "mt-4" >
407- < Button
408- color = "primary"
409- startContent = { < EditIcon /> }
410- onPress = { ( ) => setCreateNewPurchase ( true ) }
411- >
412- { t ( "new-purchase" ) }
413- </ Button >
414- </ div >
415- ) }
416- </ div >
417- }
257+ emptyContent = { emptyContent }
418258 />
419259 </ div >
420260 ) }
0 commit comments