Skip to content

Commit

Permalink
Merge pull request #30 from Saifullah-dev/feature/mock-apis
Browse files Browse the repository at this point in the history
Mock APIs Implementation
  • Loading branch information
Saifullah-dev authored Aug 22, 2024
2 parents d790b05 + 6cd4927 commit 581700c
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 124 deletions.
136 changes: 30 additions & 106 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { useState } from "react";
import FileManager from "./File Manager/FileManager";
import { createFolderAPI } from "./Mock APIs/createFolderAPI";
import { renameAPI } from "./Mock APIs/renameAPI";
import { deleteAPI } from "./Mock APIs/deleteAPI";
import { fileTransferAPI } from "./Mock APIs/fileTransferAPI";
import { refreshAPI } from "./Mock APIs/refreshAPI";

function App() {
const [isLoading, setIsLoading] = useState(false);
const [files, setFiles] = useState([
{
name: "DCIM",
Expand All @@ -24,130 +30,48 @@ function App() {
path: "",
},
]);
const [isLoading, setIsLoading] = useState(false);

// Create Folder
const handleCreateFolder = (folderName, currentPath) => {
setFiles((prev) => {
return [
...prev,
{
name: folderName,
path: currentPath,
isDirectory: true,
},
];
});
const handleCreateFolder = async (files, folderName, folderPath) => {
setIsLoading(true);
const responseFiles = await createFolderAPI(files, folderName, folderPath);
setFiles(responseFiles);
setIsLoading(false);
};
//

// Rename File/Folder
const handleRename = (selectedFile, newName) => {
setFiles((prev) => {
return prev.map((file) => {
if (file.name === selectedFile?.name && file.path === selectedFile?.path) {
return {
// Rename the file itself
...file,
name: newName,
};
} else if (file.path.startsWith(selectedFile.path + "/" + selectedFile.name)) {
// Path update for all files in the folder
const basePath = selectedFile.path + "/" + selectedFile.name;
const newBasePath = basePath.split("/").slice(0, -1).join("/") + "/" + newName;
const newPath = newBasePath + file.path.slice(basePath.length);
return {
...file,
path: newPath,
};
} else {
return file;
}
});
});
const handleRename = async (files, selectedFile, newName) => {
setIsLoading(true);
const response = await renameAPI(files, selectedFile, newName);
setFiles(response);
setIsLoading(false);
};
//

// Delete File/Folder
const handleDelete = (file) => {
if (file.isDirectory) {
setFiles((prev) => {
return prev.filter((f) => {
const folderToDelete = f.path === file.path && f.name === file.name;
const folderChildren = f.path.startsWith(file.path + "/" + file.name);
return !folderToDelete && !folderChildren;
});
});
} else {
setFiles((prev) => {
return prev.filter((f) => !(f.name === file.name && f.path === file.path));
});
}
const handleDelete = async (files, file) => {
setIsLoading(true);
const response = await deleteAPI(files, file);
setFiles(response);
setIsLoading(false);
};
//

// Paste File/Folder
const getCopiedFiles = (file, pastePath) => {
const children = file.children ?? [];
return [
{ name: file.name, isDirectory: file.isDirectory, path: pastePath },
...children.flatMap((child) => getCopiedFiles(child, pastePath + "/" + file.name)),
];
};

const handleDuplicateFile = (file, pastePath, pastePathFiles) => {
if (file.path === pastePath || pastePathFiles.find((f) => f.name === file.name)) {
const fileExtension = file.isDirectory ? "" : "." + file.name.split(".").pop();
const fileName = file.isDirectory ? file.name : file.name.split(".").slice(0, -1).join(".");

// Generating new file name for duplicate file
let maxFileNum = 0;
// If there exists a file with name fileName (1), fileName (2), etc.
// Check if the number is greater than the maxFileNum, then set it to that greater number
const fileNameRegex = new RegExp(`${fileName} \\(\\d+\\)`);
pastePathFiles.forEach((f) => {
const fName = f.isDirectory ? f.name : f.name.split(".").slice(0, -1).join(".");
if (fileNameRegex.test(fName)) {
const fileNumStr = fName.split(`${fileName} (`).pop().slice(0, -1);
const fileNum = parseInt(fileNumStr);
if (!isNaN(fileNum) && fileNum > maxFileNum) {
maxFileNum = fileNum;
}
}
});
const appendNum = ` (${++maxFileNum})`;
const newFileName = fileName + appendNum + fileExtension;
//

return { ...file, name: newFileName };
} else {
return file;
}
};

const handlePaste = (pastePath, clipBoard, filesCopied) => {
setFiles((prevFiles) => {
if (clipBoard.isMoving) {
prevFiles = prevFiles.filter((f) => {
return !filesCopied.find((cf) => cf.name === f.name && cf.path === f.path);
});
}

return [
...prevFiles,
...clipBoard.files.flatMap((file) => {
const pastePathFiles = prevFiles.filter((f) => f.path === pastePath);
const nonDuplicateFile = handleDuplicateFile(file, pastePath, pastePathFiles);
return getCopiedFiles(nonDuplicateFile, pastePath);
}),
];
});
const handlePaste = async (files, pastePath, clipBoard, filesCopied) => {
setIsLoading(true);
const response = await fileTransferAPI(files, pastePath, clipBoard, filesCopied);
setFiles(response);
setIsLoading(false);
};
//

// Refresh Files
const handleRefresh = () => {
// Refresh Files API call here...
const handleRefresh = async () => {
setIsLoading(true);
await refreshAPI();
setIsLoading(false);
};
//

Expand Down
4 changes: 4 additions & 0 deletions src/File Manager/Actions/Actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import DeleteAction from "./Delete.action";
import UploadFileAction from "./UploadFile.action";

const Actions = ({
files,
triggerAction,
currentPath,
currentPathFiles,
Expand All @@ -24,6 +25,7 @@ const Actions = ({
title: "Create Folder",
component: (
<CreateFolderAction
files={files}
currentPath={currentPath}
currentPathFiles={currentPathFiles}
triggerAction={triggerAction}
Expand All @@ -41,6 +43,7 @@ const Actions = ({
title: "Rename",
component: (
<RenameAction
files={files}
selectedFile={selectedFile}
currentPathFiles={currentPathFiles}
triggerAction={triggerAction}
Expand All @@ -54,6 +57,7 @@ const Actions = ({
title: "Delete",
component: (
<DeleteAction
files={files}
selectedFile={selectedFile}
triggerAction={triggerAction}
handleDelete={handleDelete}
Expand Down
3 changes: 2 additions & 1 deletion src/File Manager/Actions/CreateFolder.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react";
import Button from "../../components/Button/Button";

const CreateFolderAction = ({
files,
currentPath,
currentPathFiles,
handleCreateFolder,
Expand Down Expand Up @@ -45,7 +46,7 @@ const CreateFolderAction = ({

if (!alreadyExists) {
// Current path doesn't have the same folder name
handleCreateFolder(newFolderName, currentPath);
handleCreateFolder(files, newFolderName, currentPath);
triggerAction.close();
} else {
setFolderErrorMessage(`A folder with the name "${newFolderName}" already exits.`);
Expand Down
3 changes: 2 additions & 1 deletion src/File Manager/Actions/Delete.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import React from "react";
import Button from "../../components/Button/Button";

const DeleteAction = ({
files,
selectedFile,
triggerAction,
handleDelete,
setIsItemSelection,
setSelectedFile,
}) => {
const handleDeleting = (file) => {
handleDelete(file);
handleDelete(files, file);
setIsItemSelection(false);
setSelectedFile(null);
triggerAction.close();
Expand Down
3 changes: 2 additions & 1 deletion src/File Manager/Actions/Rename.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Button from "../../components/Button/Button";
import { IoWarningOutline } from "react-icons/io5";

const RenameAction = ({
files,
selectedFile,
currentPathFiles,
handleRename,
Expand Down Expand Up @@ -64,7 +65,7 @@ const RenameAction = ({
return;
}
}
handleRename(selectedFile, renameFile);
handleRename(files, selectedFile, renameFile);
setSelectedFile((prev) => ({ ...prev, name: renameFile }));
triggerAction.close();
};
Expand Down
1 change: 1 addition & 0 deletions src/File Manager/FileManager.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const FileManager = ({
</section>

<Actions
files={files}
currentPath={currentPath}
currentPathFiles={currentPathFiles}
selectedFile={selectedFile}
Expand Down
12 changes: 2 additions & 10 deletions src/File Manager/Files/FileItem.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { useEffect, useState } from "react";
import {
FaRegFile,
FaRegFileImage,
FaRegFileLines,
FaRegFilePdf,
FaRegFileWord,
FaRegFolderOpen,
FaRegPaste,
} from "react-icons/fa6";
import { FaRegFile, FaRegFolderOpen, FaRegPaste } from "react-icons/fa6";
import { PiFolderOpen } from "react-icons/pi";
import { MdOutlineDelete } from "react-icons/md";
import ContextMenu from "../../components/Context Menu/ContextMenu";
Expand Down Expand Up @@ -69,7 +61,7 @@ const FileItem = ({
);
return folderToCopy || folderChildren;
});
handlePaste(pastePath, clipBoard, copiedFiles);
handlePaste(files, pastePath, clipBoard, copiedFiles);
clipBoard.isMoving && setClipBoard(null);
setIsItemSelection(false);
setSelectedFile(null);
Expand Down
10 changes: 5 additions & 5 deletions src/File Manager/Toolbar/Toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const Toolbar = ({
];

// Handle Pasting
const handlePasting = (pastePath, clipBoard) => {
const handlePasting = (files, pastePath, clipBoard) => {
const selectedCopiedFile = clipBoard.files[0];
const copiedFiles = files.filter((f) => {
const folderToCopy = f.path === selectedCopiedFile.path && f.name === selectedCopiedFile.name;
Expand All @@ -67,7 +67,7 @@ const Toolbar = ({
return folderToCopy || folderChildren;
});

handlePaste(pastePath, clipBoard, copiedFiles);
handlePaste(files, pastePath, clipBoard, copiedFiles);
clipBoard.isMoving && setClipBoard(null);
setIsItemSelection(false);
setSelectedFile(null);
Expand All @@ -80,14 +80,14 @@ const Toolbar = ({
return {
...item,
permission: !!clipBoard,
onClick: () => handlePasting(currentPath, clipBoard),
onClick: () => handlePasting(files, currentPath, clipBoard),
};
} else {
return item;
}
});
});
}, [clipBoard, currentPath]);
}, [clipBoard, currentPath, files]);

// Handle Cut / Copy
const handleCutCopy = (isMoving) => {
Expand Down Expand Up @@ -117,7 +117,7 @@ const Toolbar = ({
{selectedFile.isDirectory ? (
<button
className="item-action file-action"
onClick={() => handlePasting(pastePath, clipBoard)}
onClick={() => handlePasting(files, pastePath, clipBoard)}
disabled={!clipBoard}
>
<FaRegPaste size={18} />
Expand Down
14 changes: 14 additions & 0 deletions src/Mock APIs/createFolderAPI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const createFolderAPI = (files, folderName, folderPath) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
...files,
{
name: folderName,
isDirectory: true,
path: folderPath,
},
]);
}, 700);
});
};
18 changes: 18 additions & 0 deletions src/Mock APIs/deleteAPI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const deleteAPI = (files, file) => {
return new Promise((resolve) => {
setTimeout(() => {
let response;
if (file.isDirectory) {
response = files.filter((f) => {
const folderToDelete = f.path === file.path && f.name === file.name;
const folderChildren = f.path.startsWith(file.path + "/" + file.name);
return !folderToDelete && !folderChildren;
});
} else {
response = files.filter((f) => !(f.name === file.name && f.path === file.path));
}

resolve(response);
}, 700);
});
};
Loading

0 comments on commit 581700c

Please sign in to comment.