62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
"use client"
|
|
|
|
import React, { useRef, useState } from "react"
|
|
import { Button } from "@/shared/components/ui/button"
|
|
import { Upload, Loader2 } from "lucide-react"
|
|
import { toast } from "sonner"
|
|
|
|
type ImportDataButtonProps = {
|
|
onImport: (file: File) => Promise<{ message?: string }>
|
|
onSuccess?: () => void
|
|
accept?: string
|
|
label?: string
|
|
}
|
|
|
|
export function ImportDataButton({
|
|
onImport,
|
|
onSuccess,
|
|
accept = ".xlsx,.xls,.csv",
|
|
label = "Import",
|
|
}: ImportDataButtonProps) {
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
const [isPending, setIsPending] = useState(false)
|
|
|
|
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = e.target.files?.[0]
|
|
if (!file) return
|
|
|
|
setIsPending(true)
|
|
try {
|
|
const result = await onImport(file)
|
|
toast.success(result.message ?? "Data imported successfully")
|
|
onSuccess?.()
|
|
} catch (err: any) {
|
|
toast.error(err?.message ?? "Failed to import data")
|
|
} finally {
|
|
setIsPending(false)
|
|
if (inputRef.current) inputRef.current.value = ""
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<input
|
|
ref={inputRef}
|
|
type="file"
|
|
accept={accept}
|
|
className="hidden"
|
|
onChange={handleFileChange}
|
|
/>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
disabled={isPending}
|
|
onClick={() => inputRef.current?.click()}
|
|
>
|
|
{isPending ? <Loader2 className="animate-spin" /> : <Upload />}
|
|
{label}
|
|
</Button>
|
|
</>
|
|
)
|
|
}
|