resume-extraction/components/file-dropper.tsx (97 lines of code) (raw):

import { FilePlus2, Trash2 } from 'lucide-react' import React, { memo, useCallback } from 'react' import { useDropzone } from 'react-dropzone' import { Document, Page, pdfjs } from 'react-pdf' import './file-dropper.css' pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs` const options = { cMapUrl: '/cmaps/', standardFontDataUrl: '/standard_fonts/' } interface FileDropperProps { file: File | null setFile: (file: File | null) => void setValues: (values: any | null) => void onFileSelected: (file: File) => void } const FileDropper: React.FC<FileDropperProps> = memo( ({ file, setFile, setValues, onFileSelected }) => { const onDrop = useCallback( (acceptedFiles: File[]) => { if (acceptedFiles.length > 0) { onFileSelected(acceptedFiles[0]) } }, [onFileSelected] ) const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'application/pdf': ['.pdf'] }, multiple: false }) const resetResume = () => { setFile(null) setValues(null) } const useExampleFile = () => { fetch('/example_resume.pdf') .then(response => response.blob()) .then(blob => { const exampleFile = new File([blob], 'example_resume.pdf', { type: 'application/pdf' }) onFileSelected(exampleFile) }) .catch(error => { console.error('Error fetching the example file:', error) }) } return ( <div className="w-full h-[90vh] flex justify-center items-center"> {file ? ( <div className="flex flex-col"> <div className="document drop-shadow-md mt-4"> <Document file={file} options={options}> <Page className="page" pageNumber={1} scale={0.8} /> </Document> </div> <div className="flex justify-center items-center mt-2"> <div className="text-xs text-neutral-600 mr-2">{file.name}</div> <Trash2 onClick={() => resetResume()} size={12} className="cursor-pointer text-neutral-800" /> </div> </div> ) : ( <div className="flex flex-col justify-center items-center"> <div {...getRootProps()} className="p-6 flex items-center justify-center relative focus-visible:outline-0" > <input {...getInputProps()} /> <div className={`absolute rounded-full transition-all duration-300 ${ isDragActive ? 'h-56 w-56 bg-stone-300' : 'h-0 w-0 bg-transparent' }`} ></div> <div className="justify-center flex flex-col items-center text-center z-10 cursor-pointer"> <FilePlus2 className="mb-4 size-8 text-stone-800" /> <div className="text-stone-700">Upload a resume</div> </div> </div> <div className="mt-2 text-sm text-stone-500"> Or{' '} <div className="inline-block border-b border-stone-400 text-stone-400 cursor-pointer hover:text-stone-500" onClick={useExampleFile} > use the example </div> </div> </div> )} </div> ) } ) FileDropper.displayName = 'FileDropper' export default FileDropper