@@ -5,9 +5,14 @@ import { useEffect, useState } from "react"
55import { Alert , AlertDescription , AlertTitle } from "~/components/ui/alert"
66import { Button } from "~/components/ui/button"
77
8- import { TableProps } from "./table "
8+ import { type Payment , type Project , type User } from "~/server/db/types "
99
10- export default function ExportButton ( { data } : TableProps ) {
10+ export interface ExportButtonProps {
11+ data : Array < Project | Payment | User >
12+ label : string
13+ }
14+
15+ export default function ExportButton ( { data, label } : ExportButtonProps ) {
1116 const [ open , setOpen ] = useState ( false )
1217 useEffect ( ( ) => {
1318 if ( ! open ) return
@@ -17,19 +22,26 @@ export default function ExportButton({ data }: TableProps) {
1722 const downloadCSV = ( ) => {
1823 if ( ! data || data . length === 0 ) {
1924 setOpen ( true )
20- console . log ( "open" )
2125 return
2226 }
2327
2428 const headers = Object . keys ( data [ 0 ] as Record < string , unknown > ) . join ( "," )
25- const rows = data . map ( ( row ) => Object . values ( row ) . join ( "," ) ) . join ( "\n" )
29+ const escapeCSV = ( value : unknown ) => {
30+ if ( value == null ) return ""
31+ const str = String ( value )
32+ if ( / [ " , \n ] / . test ( str ) ) {
33+ return `"${ str . replace ( / " / g, '""' ) } "`
34+ }
35+ return str
36+ }
37+ const rows = data . map ( ( row ) => Object . values ( row ) . map ( escapeCSV ) . join ( "," ) ) . join ( "\n" )
2638 const csv = headers + "\n" + rows
2739 const blob = new Blob ( [ csv ] , { type : "text/csv" } )
2840 const url = window . URL . createObjectURL ( blob )
2941
3042 const a = document . createElement ( "a" )
3143 a . setAttribute ( "href" , url )
32- a . setAttribute ( "download" , "output .csv" )
44+ a . setAttribute ( "download" , ` ${ label } .csv` )
3345 a . click ( )
3446 window . URL . revokeObjectURL ( url )
3547 setOpen ( true )
@@ -38,7 +50,7 @@ export default function ExportButton({ data }: TableProps) {
3850 return (
3951 < div className = "relative inline-block" >
4052 < Button onClick = { downloadCSV } variant = { "outline" } >
41- Export CSV
53+ Export { label }
4254 </ Button >
4355 { open && ( ! data || data . length === 0 ) && (
4456 < Alert variant = "destructive" className = "fixed top-30 left-1/2 -translate-x-1/2 z-50 max-w-sm" >
@@ -49,7 +61,7 @@ export default function ExportButton({ data }: TableProps) {
4961 { open && data && data . length > 0 && (
5062 < Alert variant = "default" className = "fixed top-30 left-1/2 -translate-x-1/2 z-50 max-w-sm" >
5163 < AlertTitle > Export Successful</ AlertTitle >
52- < AlertDescription > Your data has been exported as `output .csv`.</ AlertDescription >
64+ < AlertDescription > Your data has been exported as { ` ${ label } .csv`} .</ AlertDescription >
5365 </ Alert >
5466 ) }
5567 </ div >
0 commit comments