Skip to content

Commit

Permalink
drag and drop improve
Browse files Browse the repository at this point in the history
  • Loading branch information
mazmassa committed May 17, 2023
1 parent b2dbf8c commit aeb1b38
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 23 deletions.
10 changes: 1 addition & 9 deletions src/components/DragDrop/DragDrop.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,7 @@ export default { title: "Components/DragDrop", component: DragDrop };
export const _LoadFile = {
render: () => (
<>
<DragDrop placeholder="something to inform" />
</>
),
};

export const _Loaded = {
render: () => (
<>
<DragDrop placeholder="file loaded" loaded={true} />
<DragDrop placeholder="something to inform" allowed={["jpeg", "png"]} />
</>
),
};
1 change: 1 addition & 0 deletions src/components/DragDrop/DragDrop.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";

import { DragDrop } from "./DragDrop";

describe("Components | DragDrop", () => {
Expand Down
107 changes: 93 additions & 14 deletions src/components/DragDrop/DragDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,113 @@
// @ts-ignore
import React from "react";

import { ComponentPropsWithoutRef } from "react";
import { FiArchive, FiCheckCircle } from "react-icons/fi";
import { ComponentPropsWithoutRef, useState } from "react";
import { FiArchive, FiCheckCircle, FiAlertCircle } from "react-icons/fi";

export interface IDragDropProps extends ComponentPropsWithoutRef<"input"> {
interface IDragDropProps extends ComponentPropsWithoutRef<"input"> {
placeholder?: string;
loaded?: boolean;
allowed?: string[];
}

// Jest fails with Enums
// https:/kulshekhar/ts-jest/issues/3397
// this would be Status enum { NORMAL = "normal", ...}
const NORMAL = "normal";
const FAILED = "failed";
const LOADED = "loaded";
const Status = { NORMAL, FAILED, LOADED };

const LoadedStatus = {
normal: {
style: "text-tertiary",
icon: <FiArchive className="w-12 h-12" />,
},
failed: {
style: "text-s-error",
icon: <FiAlertCircle className="w-12 h-12" />,
},
loaded: {
style: "text-s-success",
icon: <FiCheckCircle className="w-12 h-12" />,
},
};

export function DragDrop(props: IDragDropProps) {
const { placeholder, loaded = false } = props;
const { placeholder, allowed = [".yaml"] } = props;

const [isLoaded, setIsLoaded] = useState(Status.NORMAL);
const [fileName, setFileName] = useState(placeholder);

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const loadedClass = LoadedStatus[isLoaded].style;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const loadedIcon = LoadedStatus[isLoaded].icon;

function isValidFile(file: string) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (!allowed.includes(file.split(".").pop())) {
setIsLoaded(Status.FAILED);
setFileName(`Owh! File not allowed. Allowed: ${allowed.toString()}`);
return false;
}
return true;
}

function dropHandler(e: {
preventDefault: () => void;
dataTransfer: { items: any; files: any };
}) {
e.preventDefault();

if (e.dataTransfer.items) {
[...e.dataTransfer.items].forEach((item) => {
if (item.kind === "file") {
const file = item.getAsFile();

if (!isValidFile(file.name.toLowerCase() || "")) {
return;
} else {
setIsLoaded(Status.LOADED);
setFileName(file.name);
}
}
});
} else {
[...e.dataTransfer.files].forEach((file) => {
if (!isValidFile(file.name.toLowerCase())) {
return;
} else {
setIsLoaded(Status.LOADED);
setFileName(file.name);
}
});
}
}

const loadedClass = loaded ? "text-s-success" : "text-tertiary";
function dragOverHandler(e: { preventDefault: () => void }) {
e.preventDefault();
}

return (
<div data-testid="drag-drop" className="w-full">
<div
data-testid="drag-drop"
className="w-full"
id="drop_zone"
onDrop={dropHandler}
onDragOver={dragOverHandler}
>
<label
className={`flex justify-center w-full h-24 px-4 transition ${loadedClass}
bg-secondary rounded-lg appearance-none cursor-pointer`}
>
<span className="flex items-center space-x-2">
{loaded ? (
<FiCheckCircle className="w-12 h-12" />
) : (
<FiArchive className="w-12 h-12" />
)}
<span className="pl-5 mas-body2">{placeholder}</span>
{loadedIcon}
<span className="pl-5 mas-body2">{fileName}</span>
</span>
<input type="file" name="upload" className="hidden" />
<input accept="*.yaml" type="file" name="upload" className="hidden" />
</label>
</div>
);
Expand Down

0 comments on commit aeb1b38

Please sign in to comment.