LinkList/frontend/components/Editor/index.tsx

138 lines
4.5 KiB
TypeScript

import React, { useState, useEffect } from "react";
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import Link, { EditableLink } from "components/Editor/Link";
import { useAuth } from "components/Login/AuthContext";
import Preview from "components/Preview";
import { useDragDrop } from "./useDragDrop";
import equal from "fast-deep-equal";
interface EditorProps {
links: EditableLink[];
setLinks: React.Dispatch<React.SetStateAction<EditableLink[]>>;
}
const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
const { displayDragDrop } = useDragDrop();
const { headers } = useAuth();
const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links);
useEffect(() => {
setEditableLinks(links);
}, [links]);
const handleOnDragEnd = (result: DropResult) => {
if (!result?.destination) return;
const items = Array.from(editableLinks);
const [reorderedItem] = items.splice(result.source.index, 1);
items.splice(result.destination.index, 0, reorderedItem);
setEditableLinks(items);
};
/*note that we need to make the new links name render with nothing*/
const handleOnClickAdd = () =>
setEditableLinks([
...editableLinks,
{
name: "",
url: "",
clicks: 0,
active: true,
},
]);
const onSubmit = async () => {
const res = await fetch("/api/editor/links", {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers,
},
body: JSON.stringify({ links: editableLinks }),
});
const updatedLinks = await res.json();
setLinks(updatedLinks);
};
const onCancel = () => {
setEditableLinks(links);
};
return (
<div className="flex flex-col bg-gray-100 md:h-full md:flex-row">
<div className="space-y-4 md:w-3/5 md:border-r md:border-gray-300 md:overflow-y-scroll">
<div className="m-8">
<button
className="block flex py-2 items-center justify-center rounded-lg bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full"
onClick={handleOnClickAdd}
>
Add New Link
</button>
<div className="mb-8" />
{displayDragDrop && (
<DragDropContext onDragEnd={handleOnDragEnd}>
<Droppable droppableId="links">
{(provided) => (
<div
className="links"
{...provided.droppableProps}
ref={provided.innerRef}
>
{editableLinks.map((link, index) => (
<Link
key={index}
index={index}
link={link}
onChange={(newLink: EditableLink) =>
setEditableLinks([
...editableLinks.slice(0, index),
newLink,
...editableLinks.slice(index + 1),
])
}
onDelete={() =>
setEditableLinks([
...editableLinks.slice(0, index),
...editableLinks.slice(index + 1),
])
}
/>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
)}
<div className="mb-8" />
<div className="flex">
<button
className="block flex py-2 items-center justify-center rounded-lg bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onSubmit}
disabled={equal(editableLinks, links)}
>
Submit
</button>
<div className="mr-4" />
<button
className="block flex py-2 items-center justify-center rounded-lg bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onCancel}
disabled={equal(editableLinks, links)}
>
Cancel
</button>
</div>
</div>
</div>
<div className="mb-8 md:none" />
<div className="flex items-center justify-center md:w-2/5">
<Preview links={editableLinks.filter((link) => link.active)} />
</div>
</div>
);
};
export default Editor;