Skip to content

Commit

Permalink
Merge pull request #381 from Sid-80/feat/376
Browse files Browse the repository at this point in the history
Feat/376
  • Loading branch information
subhadeeproy3902 authored Jul 1, 2024
2 parents 30fcd9d + 5d81ff5 commit cd99a88
Show file tree
Hide file tree
Showing 5 changed files with 525 additions and 9 deletions.
394 changes: 394 additions & 0 deletions src/app/dashboard/team/_components/FileList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,394 @@
import { useState, useEffect } from "react";
import {
Loader2,
Trash2,
ChevronsUpDown,
ArchiveIcon,
ArchiveRestore,
Clock,
Edit,
CheckCircle2,
EyeIcon,
Edit3Icon,
} from "lucide-react";
import moment from "moment";
import Image from "next/image";
import { usePathname, useRouter } from "next/navigation";
import { useConvex, useMutation } from "convex/react";
import { Button } from "@/components/ui/button";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";

export interface FILE {
archive: boolean;
createdBy: string;
document: string;
fileName: string;
teamId: string;
whiteboard: string;
_id: string;
_creationTime: number;
private: boolean;
read: boolean;
write: boolean;
readBy: string[];
writtenBy: string[];
}

const ActionDialog = ({
buttonIcon: ButtonIcon,
dialogTitle,
dialogDescription,
onAction,
buttonVariant = "secondary",
isSubmitted,
successTitle,
}: {
buttonIcon: typeof ArchiveIcon;
dialogTitle: string;
dialogDescription: string;
onAction: (e: any) => void;
buttonVariant?:
| "secondary"
| "link"
| "default"
| "destructive"
| "outline"
| "ghost"
| null;
isSubmitted: boolean;
successTitle: string;
}) => (
<AlertDialog>
<AlertDialogTrigger>
<Button variant={buttonVariant} size="icon">
<ButtonIcon className="h-4 w-4" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
{!isSubmitted && (
<>
<AlertDialogHeader>
<AlertDialogTitle>{dialogTitle}</AlertDialogTitle>
<AlertDialogDescription>{dialogDescription}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button onClick={onAction}>Continue</Button>
</AlertDialogFooter>
</>
)}
{isSubmitted && (
<>
<AlertDialogHeader>
<AlertDialogTitle className="flex gap-2">
<p>{successTitle}</p> <CheckCircle2 className="w-6 h-6" />
</AlertDialogTitle>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogAction
onClick={() => {
window.location.reload();
}}
>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</>
)}
</AlertDialogContent>
</AlertDialog>
);

const FileRow = ({
file,
router,
user
}: {
file: FILE;
user:any;
router: ReturnType<typeof useRouter>;
}) => (
<tr key={file._id} className="odd:bg-muted/50 cursor-pointer">
<td
className="whitespace-nowrap px-4 py-2 font-medium"
onClick={() => router.push("/workspace/" + file._id)}
>
{file.fileName}
</td>
<td
className="whitespace-nowrap px-4 py-2 text-muted-foreground"
onClick={() => router.push("/workspace/" + file._id)}
>
{file.createdBy}
</td>
<td
className="whitespace-nowrap px-4 py-2 text-muted-foreground"
onClick={() => router.push("/workspace/" + file._id)}
>
{file.readBy && file.readBy.includes(user.email) && <Badge>Read</Badge>}
{file.writtenBy && file.writtenBy.includes(user.email) && <Badge>Write</Badge>}
{!file.readBy && !file.writtenBy && <Badge>No Access</Badge>}
</td>
<td className="flex gap-2 whitespace-nowrap px-4 py-2 text-muted-foreground">
<Button><EyeIcon size={"icon"} className="w-5 h-5" /></Button>
<Button><Edit3Icon size={"icon"} className="w-5 h-5" /></Button>
{/* <RenameFileModal id={file._id} />
{pathname === "/dashboard" && (
<ActionDialog
isSubmitted={isSubmitted}
successTitle="File Archived Successfully!!"
buttonIcon={ArchiveIcon}
dialogTitle="Are you absolutely sure?"
dialogDescription="This will add your file to the archive section."
onAction={(e) => onArchive(e, file._id)}
/>
)}
{pathname === "/dashboard/archive" && (
<ActionDialog
isSubmitted={isSubmitted}
successTitle="File Restored Successfully!!"
buttonIcon={ArchiveRestore}
dialogTitle="Are you absolutely sure?"
dialogDescription="This will unarchive your file."
onAction={(e) => onUnarchive(e, file._id)}
buttonVariant="destructive"
/>
)}
<ActionDialog
buttonIcon={Trash2}
isSubmitted={isSubmitted}
successTitle="File Deleted Successfully!!"
dialogTitle="Are you absolutely sure?"
dialogDescription="This action cannot be undone. This will permanently delete your file and remove your data from our servers."
onAction={(e) => onDelete(e, file._id)}
buttonVariant="destructive"
/> */}
</td>
</tr>
);

function FileList({
fileList,
user
}: {
fileList?: FILE[];
user:any;
}) {
const router = useRouter();
const convex = useConvex();
const [sortConfig, setSortConfig] = useState<{
key: keyof FILE;
direction: string;
} | null>(null);
const [isSmallScreen, setIsSmallScreen] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [authorData, setAuthorData] = useState<any[]>([]);
const safeFileList = Array.isArray(fileList) ? fileList : [];
const pathname = usePathname();

console.log(fileList)

const sortedFiles = [...safeFileList];
if (sortConfig !== null) {
sortedFiles.sort((a, b) => {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === "ascending" ? -1 : 1;
}
if (a[sortConfig.key] > b[sortConfig.key]) {
return sortConfig.direction === "ascending" ? 1 : -1;
}
return 0;
});
}

const requestSort = (key: keyof FILE) => {
let direction = "ascending";
if (
sortConfig &&
sortConfig.key === key &&
sortConfig.direction === "ascending"
) {
direction = "descending";
}
setSortConfig({ key, direction });
};

useEffect(() => {
const handleResize = () => {
setIsSmallScreen(window.innerWidth < 768);
};
handleResize();
window.addEventListener("resize", handleResize);

return () => {
window.removeEventListener("resize", handleResize);
};
}, []);

return (
<div className="mt-10">
<div className="overflow-x-auto">
{!isSmallScreen ? (
<table className="min-w-full divide-y-2 overflow-hidden text-sm">
<thead className="ltr:text-left rtl:text-right">
<tr>
<td
className="whitespace-nowrap px-4 py-2 font-medium cursor-pointer"
onClick={() => requestSort("fileName")}
>
File Name <ChevronsUpDown className="inline-block ml-2" />
</td>
<td className="whitespace-nowrap px-4 py-2 font-medium">
Author
</td>
<td className="whitespace-nowrap px-4 py-2 font-medium">
Access
</td>
</tr>
</thead>
<tbody className="divide-y divide-stone-600">
{!fileList && (
<tr className="relative h-16">
<td className="whitespace-nowrap w-full absolute px-4 py-2 mt-5 text-center font-medium flex-center">
<Loader2 className="animate-spin mr-3" size={20} />{" "}
Loading... Please wait
</td>
</tr>
)}
{fileList && !safeFileList.length && (
<tr className="relative h-16">
<td className="whitespace-nowrap text-secondary-foreground w-full absolute px-4 py-2 mt-5 text-center font-medium">
No files found
</td>
</tr>
)}
{(sortedFiles.length > 0 ? sortedFiles : safeFileList).map(
(file, index) => (
<FileRow
user={user}
key={index}
file={file}
router={router} />
)
)}
</tbody>
</table>
) : (
<div>
<div className="flex justify-between px-4 py-2 font-medium bg-muted/50">
<div
className="cursor-pointer"
onClick={() => requestSort("fileName")}
>
File Name <ChevronsUpDown className="inline-block ml-2" />
</div>
<div
className="cursor-pointer"
onClick={() => requestSort("_creationTime")}
>
Created At <ChevronsUpDown className="inline-block ml-2" />
</div>
</div>
{sortedFiles.map((file, index) => (
<div
onClick={() => router.push("/workspace/" + file._id)}
key={index}
className={`border p-4 mb-4 rounded ${index % 2 === 0 ? "bg-muted/50" : ""}`}
>
<div className="flex justify-between items-center mb-2">
<span className="font-bold text-xl">{file.fileName}</span>
<div className="flex gap-2">
{/* <RenameFileModal id={file._id} />
{pathname === "/dashboard" && (
<ActionDialog
isSubmitted={isSubmitted}
successTitle="File Archived Successfully!!"
buttonIcon={ArchiveIcon}
dialogTitle="Are you absolutely sure?"
dialogDescription="This will add your file to the archive section."
onAction={(e) => archiveFunc(e, file._id)}
/>
)}
{pathname === "/dashboard/archive" && (
<ActionDialog
isSubmitted={isSubmitted}
successTitle="File Restored Successfully!!"
buttonIcon={ArchiveRestore}
dialogTitle="Are you absolutely sure?"
dialogDescription="This will unarchive your file."
onAction={(e) => unarchiveFunc(e, file._id)}
buttonVariant="destructive"
/>
)}
<ActionDialog
isSubmitted={isSubmitted}
successTitle="File Deleted Successfully!!"
buttonIcon={Trash2}
dialogTitle="Are you absolutely sure?"
dialogDescription="This action cannot be undone. This will permanently delete your file and remove your data from our servers."
onAction={(e) => deleteFunc(e, file._id)}
buttonVariant="destructive"
/> */}
</div>
</div>
<div className="flex justify-between items-center mb-2">
<div className="flex flex-col">
<div className="mb-2 text-muted-foreground">
<Clock className="inline-block mr-2" size={20} />
{moment(file._creationTime).format("YYYY-MM-DD")}
</div>
<div className="mb-2 text-muted-foreground">
<Edit className="inline-block mr-2" size={20} />
{moment(file._creationTime).format("YYYY-MM-DD")}
</div>
</div>
{/* <FileStatusModal
fileId={file._id}
email={user.email}
privateFIle={file.private}
successTitle={
!file.private
? "File accessible to members only"
: "File accessible to everyone"
}
dialogTitle={
!file.private ? "Private File" : "Public File"
}
dialogDescription={
!file.private
? "Make file accessible to members only"
: "Make file accessible to everyone"
}
/> */}
</div>

<div className="text-muted-foreground flex justify-end">
{/* <Image
src={}
alt="user"
width={30}
height={30}
className="rounded-full"
/> */}
</div>
</div>
))}
</div>
)}
</div>
</div>
);
}

export default FileList;
Loading

0 comments on commit cd99a88

Please sign in to comment.