LinkList/frontend/components/Editor/index.tsx

138 lines
4.5 KiB
TypeScript
Raw Normal View History

2021-04-02 16:14:50 -04:00
import React, { useState, useEffect } from "react";
2021-04-01 18:26:56 -04:00
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import Link, { EditableLink } from "components/Editor/Link";
2021-04-03 21:01:00 -04:00
import { useAuth } from "components/Login/AuthContext";
2021-04-04 11:35:14 -04:00
import Preview from "components/Preview";
2021-04-01 18:26:56 -04:00
import { useDragDrop } from "./useDragDrop";
import equal from "fast-deep-equal";
interface EditorProps {
links: EditableLink[];
setLinks: React.Dispatch<React.SetStateAction<EditableLink[]>>;
}
2021-04-03 21:01:00 -04:00
const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
2021-04-01 18:26:56 -04:00
const { displayDragDrop } = useDragDrop();
2021-04-03 21:01:00 -04:00
const { headers } = useAuth();
2021-04-05 11:00:14 -04:00
const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links);
2021-04-01 18:26:56 -04:00
2021-04-02 16:14:50 -04:00
useEffect(() => {
2021-04-05 11:00:14 -04:00
setEditableLinks(links);
2021-04-02 16:14:50 -04:00
}, [links]);
2021-04-01 18:26:56 -04:00
const handleOnDragEnd = (result: DropResult) => {
if (!result?.destination) return;
2021-04-05 11:00:14 -04:00
const items = Array.from(editableLinks);
2021-04-01 18:26:56 -04:00
const [reorderedItem] = items.splice(result.source.index, 1);
items.splice(result.destination.index, 0, reorderedItem);
2021-04-05 11:00:14 -04:00
setEditableLinks(items);
2021-04-01 18:26:56 -04:00
};
/*note that we need to make the new links name render with nothing*/
const handleOnClickAdd = () =>
2021-04-05 11:00:14 -04:00
setEditableLinks([
...editableLinks,
2021-04-01 18:26:56 -04:00
{
2021-04-02 16:14:50 -04:00
name: "",
2021-04-01 18:26:56 -04:00
url: "",
clicks: 0,
active: true,
},
]);
2021-04-03 21:01:00 -04:00
const onSubmit = async () => {
const res = await fetch("/api/editor/links", {
method: "POST",
headers: {
"Content-Type": "application/json",
...headers,
},
2021-04-05 11:00:14 -04:00
body: JSON.stringify({ links: editableLinks }),
2021-04-03 21:01:00 -04:00
});
const updatedLinks = await res.json();
setLinks(updatedLinks);
2021-04-01 18:26:56 -04:00
};
2021-04-03 21:01:00 -04:00
const onCancel = () => {
2021-04-05 11:00:14 -04:00
setEditableLinks(links);
2021-04-03 21:01:00 -04:00
};
2021-04-01 18:26:56 -04:00
return (
2021-04-07 18:05:07 -04:00
<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">
2021-04-04 11:35:14 -04:00
<button
2021-04-07 18:05:07 -04:00
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}
2021-04-04 11:35:14 -04:00
>
2021-04-07 18:05:07 -04:00
Add New Link
2021-04-04 11:35:14 -04:00
</button>
2021-04-07 18:05:07 -04:00
<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>
2021-04-04 11:35:14 -04:00
</div>
2021-04-03 21:01:00 -04:00
</div>
2021-04-07 18:05:07 -04:00
<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>
2021-04-01 18:26:56 -04:00
</div>
);
};
export default Editor;