Skip to content

Commit

Permalink
refactor(member): improved Uploader Component UI (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
gwansikk committed Mar 30, 2024
1 parent 6358a48 commit 3b4b7ac
Showing 1 changed file with 87 additions and 19 deletions.
106 changes: 87 additions & 19 deletions apps/member/src/components/common/Uploader/Uploader.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,92 @@
import { ComponentPropsWithRef, forwardRef } from 'react';
import { Input } from '@clab/design-system';
import classNames from 'classnames';
import { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import { BsImage, BsFileEarmarkArrowUp } from 'react-icons/bs';
import { Button } from '@clab/design-system';

interface UploaderProps extends ComponentPropsWithRef<'input'> {
label: string;
interface UploaderProps {
label?: string;
accept: string;
maxFiles?: number;
multiple?: boolean;
onFileAccepted: (file: File | null) => void;
}

const Uploader = forwardRef<HTMLInputElement, UploaderProps>(
({ label, className, ...rest }, ref) => {
return (
<Input
type="file"
ref={ref}
id={label}
label={label}
className={classNames('col-span-2 border-none', className)}
{...rest}
/>
);
},
);
const Uploader = ({
label,
accept,
maxFiles = 1,
multiple = false,
onFileAccepted,
}: UploaderProps) => {
/**
* 파일이 인식되었을 때 실행되는 콜백 함수입니다.
*/
const onDrop = useCallback(
(acceptedFiles: File[]) => {
const file = acceptedFiles[0];
if (file) {
onFileAccepted(file);
}
},
[onFileAccepted],
);
/**
* 파일 선택 취소 시 실행되는 콜백 함수입니다.
*/
const onFileDialogCancel = useCallback(() => {
onFileAccepted(null);
}, [onFileAccepted]);

/**
* Dropzone 라이브러리를 위한 설정값입니다.
*/
const { getRootProps, getInputProps, isDragActive, acceptedFiles } =
useDropzone({
onDrop,
onFileDialogCancel,
maxFiles: maxFiles,
multiple: multiple,
accept: { [accept]: [] },
});

return (
<div className="flex flex-col">
{label && <label className="mb-1 ml-1 text-xs">{label}</label>}
<div
className="flex items-center justify-center text-gray-600 border-2 border-dashed rounded-lg cursor-pointer min-h-56 bg-gray-50"
{...getRootProps()}
>
<input {...getInputProps()} />
<div className="flex flex-col items-center justify-center gap-2 px-4 text-sm text-center break-keep">
{acceptedFiles.length ? (
<ul className="leading-loose">
{acceptedFiles.map((file, index) => (
<li key={index}>
{file.name} - {file.size} bytes
</li>
))}
<li>
{acceptedFiles.length}개의 파일이 첨부됐어요,&nbsp;
<u>클릭하면 다시 업로드</u> 할 수 있어요.
</li>
</ul>
) : isDragActive ? (
<>
<BsFileEarmarkArrowUp size={46} />
<p>파일이 인식됐어요, 지금 놓으시면 돼요!</p>
</>
) : (
<>
<BsImage size={46} />
<p>파일을 여기로 끌어다 놓아주세요.</p>
<p>또는</p>
<Button type="button">파일 선택하기</Button>
</>
)}
</div>
</div>
</div>
);
};

export default Uploader;

0 comments on commit 3b4b7ac

Please sign in to comment.