Skip to content

Commit

Permalink
ui(file upload)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeddnyx committed Jun 22, 2024
1 parent 2ebb094 commit 40ae54a
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 44 deletions.
10 changes: 7 additions & 3 deletions components/form/input-file/file-multiple.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"use client";
import FileInput from "@/components/ui/form/File";
import { useState } from "react";

import FileInput from "@/components/ui/form/File";

export default function File() {
const [file, setFile] = useState<File[]>([]);

return (
<FileInput
file={file}
Expand All @@ -12,8 +14,10 @@ export default function File() {
preview="file"
isMultiple
>
<p className="hover:underline">Click here</p>
<p>or drag and drop</p>
<div className="flex flex-col items-center justify-center p-2">
<p>Click here</p>
<p>or drag and drop here</p>
</div>
</FileInput>
);
}
14 changes: 10 additions & 4 deletions components/form/input-file/file.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
"use client";
import Button from "@/components/ui/component/Button";
import FileInput from "@/components/ui/form/File";
import { useState } from "react";

import FileInput from "@/components/ui/form/File";
import { cn } from "@/lib/utils";

export default function File() {
const [file, setFile] = useState<File[]>([]);

return (
<FileInput file={file} setFile={setFile} name="file" preview="file">
<Button text="Click here" />
<p>or drag and drop</p>
<div
className={cn(`h-20 flex items-center flex-col justify-center p-2`, {})}
>
<p>Click here</p>
<p>or drag and drop here</p>
</div>
</FileInput>
);
}
21 changes: 16 additions & 5 deletions components/form/input-file/image-multiple.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
"use client";
import Button from "@/components/ui/component/Button";
import FileInput from "@/components/ui/form/File";
import { useState } from "react";

import FileInput from "@/components/ui/form/File";
import { cn } from "@/lib/utils";

export default function Image() {
const [file, setFile] = useState<File[]>([]);
return (
<FileInput file={file} setFile={setFile} name="file" preview="img" isMultiple>
<Button text="Click here" />
<p>or drag and drop</p>
<FileInput
file={file}
setFile={setFile}
name="file"
preview="img"
isMultiple
>
<div
className={cn(`h-20 flex items-center flex-col justify-center p-2`, {})}
>
<p>Click here</p>
<p>or drag and drop here</p>
</div>
</FileInput>
);
}
12 changes: 9 additions & 3 deletions components/form/input-file/image.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
"use client";
import Button from "@/components/ui/component/Button";
import FileInput from "@/components/ui/form/File";
import { useState } from "react";

import FileInput from "@/components/ui/form/File";
import { cn } from "@/lib/utils";

export default function Image() {
const [file, setFile] = useState<File[]>([]);
return (
<FileInput file={file} setFile={setFile} name="file" preview="img" accept="file">
<p>or drag and drop</p>
<div
className={cn(`h-20 flex items-center flex-col justify-center p-2`, {})}
>
<p>Click here</p>
<p>or drag and drop here</p>
</div>
</FileInput>
);
}
26 changes: 20 additions & 6 deletions components/form/input-file/preview-file.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
import { convertSizeBytes } from "@/lib/utils";
import { FaFile } from "react-icons/fa";
import { MdClose } from "react-icons/md";

export default function PreviewFile({ file }: { file: File }) {
export default function PreviewFile({
file,
handleDelete,
}: {
file: File;
handleDelete: () => void;
}) {
return (
<div className="flex justify-start w-full items-center gap-4 p-1 px-2 rounded-lg bg-dark-400">
<FaFile size={35} />
<div>
<p>{file?.name}</p>
<p className="text-xs">{convertSizeBytes(file?.size)}</p>
<div className="flex justify-between h-16 w-full items-center rounded-lg !p-0 bg-dark-400">
<div className="p-1 px-2 flex justify-start items-center gap-4">
<FaFile size={35} />
<div>
<p>{file?.name}</p>
<p className="text-xs">{convertSizeBytes(file?.size)}</p>
</div>
</div>
<MdClose
size={20}
className="cursor-pointer h-full w-14 px-5 transition-colors hover:bg-red-500 rounded-tr-lg"
onClick={handleDelete}
/>
</div>
);
}
20 changes: 16 additions & 4 deletions components/form/input-file/preview-img.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import Image from "next/image";
import { MdClose } from "react-icons/md";

export default function PreviewImg({ file }: { file: File|null }) {
if(!file) return null
export default function PreviewImg({
file,
handleDelete,
}: {
file: File | null;
handleDelete: () => void;
}) {
if (!file) return null;

return (
<div>
<div className="relative size-40 bg-dark-400 rounded-lg">
<Image
src={URL?.createObjectURL(file)}
alt={file?.name}
className="size-40 rounded-lg object-cover"
className="size-40 object-cover"
width={40}
height={40}
/>
<MdClose
className="size-6 absolute top-0 right-0 cursor-pointer transition-colors bg-red-500 rounded-bl-lg rounded-tr-lg"
size={15}
onClick={handleDelete}
/>
</div>
);
}
59 changes: 42 additions & 17 deletions components/ui/form/File.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useRef } from "react";
import { useRef, useState } from "react";

import PreviewFile from "@/components/form/input-file/preview-file";
import PreviewImg from "@/components/form/input-file/preview-img";
import { cn } from "@/lib/utils";

export default function File({
file,
Expand All @@ -15,9 +16,11 @@ export default function File({
preview = "img",
isMultiple = false,
accept = "image/*,.pdf",
maxSize = 10 * 1024 * 1024, // 10MB
maxSize = 10 * 1024 * 1024, //10MB
...props
}: IUploadFile) {
const refFile = useRef<HTMLInputElement>(null);
const [isActive, setIsActive] = useState(false);

const handleFileUpload = async (files: File) => {
const acceptedTypes = ["image/jpeg", "image/png", "application/pdf"];
Expand All @@ -44,6 +47,7 @@ export default function File({

const handleDrop = async (e: React.DragEvent) => {
e.preventDefault();
setIsActive(false);
const file = e.dataTransfer?.files?.[0];
file && (await handleFileUpload(file));
};
Expand All @@ -53,17 +57,27 @@ export default function File({
file && (await handleFileUpload(file));
};

// const handleDelete = async () => {
// const files = file?.split("/").pop();
// pass a func delete here
// };
const handleOver = (e: React.DragEvent) => {
e.preventDefault();
setIsActive(true);
};

const handleDelete = (id: number) => {
setFile((file) => file.filter((_, index) => index !== id));
};

return (
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
onClick={() => refFile.current?.click()}
className="w-full"
onDragOver={handleOver}
onDragLeave={() => setIsActive(false)}
className={cn(
`h-fit w-full flex items-center flex-col justify-center p-2`,
{
"border-2 border-dashed": isActive,
},
)}
{...props}
>
<input
type="file"
Expand All @@ -76,31 +90,42 @@ export default function File({

{isMultiple && preview === "img" && file?.length > 0 && (
<div className="flex flex-col gap-5 w-full">
{children}
<div className="flex gap-2">
<div onClick={() => refFile.current?.click()}>{children}</div>
<div className="flex gap-2 flex-wrap justify-between gap-y-4">
{file?.map((item, id) => {
return <PreviewImg key={id} file={item} />;
return <PreviewImg key={id} file={item} handleDelete={() => handleDelete(id)} />;
})}
</div>
</div>
)}
{isMultiple && preview === "file" && file?.length > 0 && (
<div className="flex flex-col gap-5 w-full">
{children}
<div onClick={() => refFile.current?.click()}>{children}</div>
<div className="flex gap-2 flex-col items-center w-full">
{file?.map((item, id) => {
return <PreviewFile key={id} file={item} />;
return (
<PreviewFile
key={id}
file={item}
handleDelete={() => handleDelete(id)}
/>
);
})}
</div>
</div>
)}
{!isMultiple && preview === "img" && file?.length > 0 && (
<PreviewImg file={file && file[0]} />
<PreviewImg file={file && file[0]} handleDelete={() => handleDelete(0)} />
)}
{!isMultiple && preview === "file" && file?.length > 0 && (
<PreviewFile file={file && file[0]} />
<PreviewFile
file={file && file[0]}
handleDelete={() => handleDelete(0)}
/>
)}
{file?.length === 0 && (
<div onClick={() => refFile.current?.click()}>{children}</div>
)}
{file?.length === 0 && children}
</div>
);
}
4 changes: 4 additions & 0 deletions constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ export const SIDEBAR_ITEMS: ISidebar[] = [
title: "Scroll Based",
href: ROUTES.animationUrl("scroll-based"),
},
{
title: "Scroll Opacity",
href: ROUTES.animationUrl("scroll-opacity"),
},
{
title: "Directionally Aware",
href: ROUTES.animationUrl("directionally-aware"),
Expand Down
4 changes: 2 additions & 2 deletions types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ declare interface IOtp {
disabled?: boolean;
}

interface IUploadFile {
interface IUploadFile extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
accept?: string;
isLoading?: boolean;
setIsLoading?: React.Dispatch<React.SetStateAction<boolean>>;
Expand Down Expand Up @@ -104,7 +104,7 @@ declare interface IAcordion {
}
declare interface IAcordionImage {
image: string | any;
logo?: React.ReactNode ;
logo?: React.ReactNode;
title: string;
description: string;
className?: string;
Expand Down

0 comments on commit 40ae54a

Please sign in to comment.