feat: delete lists
This commit is contained in:
@@ -29,7 +29,7 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
||||
<div className="flex h-full w-full">
|
||||
<nav className="flex w-72 flex-col justify-between border-r border-dark-600 px-5 py-5">
|
||||
<div>
|
||||
<ul role="list" className="-mx-2 my-6 space-y-1">
|
||||
<ul role="list" className="-mx-2 my-3 space-y-1">
|
||||
{navigation.map((item) => (
|
||||
<li key={item.name}>
|
||||
<ReactiveButton
|
||||
@@ -42,7 +42,6 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button className="flex items-center">
|
||||
{session?.user.image ? (
|
||||
<Image
|
||||
@@ -52,12 +51,23 @@ export default async function Layout(props: { children: React.ReactNode }) {
|
||||
height={30}
|
||||
alt=""
|
||||
/>
|
||||
) : null}
|
||||
<p className="ml-2 truncate text-sm text-dark-1000">
|
||||
) : (
|
||||
<span className="inline-block h-6 w-6 overflow-hidden rounded-full bg-dark-400">
|
||||
<svg
|
||||
className="h-full w-full text-dark-700"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||
</svg>
|
||||
</span>
|
||||
)}
|
||||
<p className="ml-2 truncate text-sm text-dark-900">
|
||||
{session?.user.email}
|
||||
</p>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div className="w-full overflow-hidden">{props.children}</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
58
src/app/boards/[...id]/DeleteListConfirmation.tsx
Normal file
58
src/app/boards/[...id]/DeleteListConfirmation.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
"use client";
|
||||
|
||||
import { api } from "~/trpc/react";
|
||||
import { useBoard } from "~/app/providers/board";
|
||||
import { useModal } from "~/app/providers/modal";
|
||||
|
||||
interface DeleteListConfirmationProps {
|
||||
listPublicId: string;
|
||||
}
|
||||
|
||||
export function DeleteListConfirmation({
|
||||
listPublicId,
|
||||
}: DeleteListConfirmationProps) {
|
||||
const utils = api.useUtils();
|
||||
const { boardData } = useBoard();
|
||||
const { closeModal } = useModal();
|
||||
|
||||
const refetchBoard = () =>
|
||||
utils.board.byId.refetch({ id: boardData.publicId });
|
||||
|
||||
const deleteList = api.list.delete.useMutation({
|
||||
onSuccess: async () => {
|
||||
closeModal();
|
||||
await refetchBoard();
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full flex-col justify-between pb-4">
|
||||
<h2 className="text-md pb-4 font-medium text-dark-1000">
|
||||
Are you sure you want to delete this list?
|
||||
</h2>
|
||||
<p className="text-sm font-medium text-dark-900">
|
||||
{"This action can't be undone."}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-5 flex justify-end sm:mt-6">
|
||||
<button
|
||||
className="mr-4 inline-flex justify-center rounded-md border-[1px] border-dark-600 bg-dark-300 px-3 py-2 text-sm font-semibold text-dark-1000 shadow-sm focus-visible:outline-none"
|
||||
onClick={() => closeModal()}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={() =>
|
||||
deleteList.mutate({
|
||||
listPublicId,
|
||||
})
|
||||
}
|
||||
className="inline-flex justify-center rounded-md bg-dark-1000 px-3 py-2 text-sm font-semibold text-dark-50 shadow-sm focus-visible:outline-none"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
54
src/app/boards/[...id]/ListDropdown.tsx
Normal file
54
src/app/boards/[...id]/ListDropdown.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Fragment } from "react";
|
||||
import { Menu, Transition } from "@headlessui/react";
|
||||
import { HiEllipsisHorizontal } from "react-icons/hi2";
|
||||
import { useModal } from "~/app/providers/modal";
|
||||
|
||||
interface ListDropdownProps {
|
||||
setSelectedPublicListId: () => void;
|
||||
}
|
||||
|
||||
export default function ListDropdown({
|
||||
setSelectedPublicListId,
|
||||
}: ListDropdownProps) {
|
||||
const { openModal } = useModal();
|
||||
|
||||
const handleOpenDeleteListConfirmation = () => {
|
||||
setSelectedPublicListId();
|
||||
openModal("DELETE_LIST");
|
||||
};
|
||||
|
||||
return (
|
||||
<Menu as="div" className="relative inline-block text-left">
|
||||
<div>
|
||||
<Menu.Button className="mr-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400">
|
||||
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
|
||||
</Menu.Button>
|
||||
</div>
|
||||
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
leave="transition ease-in duration-75"
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items className="absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md border border-dark-400 bg-dark-300 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
<div className="flex">
|
||||
<Menu.Item>
|
||||
{() => (
|
||||
<button
|
||||
onClick={handleOpenDeleteListConfirmation}
|
||||
className="m-1 w-full rounded-[5px] px-3 py-2 text-left text-sm text-dark-1000 hover:bg-dark-400"
|
||||
>
|
||||
Delete list
|
||||
</button>
|
||||
)}
|
||||
</Menu.Item>
|
||||
</div>
|
||||
</Menu.Items>
|
||||
</Transition>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
@@ -18,6 +18,8 @@ import { useModal } from "~/app/providers/modal";
|
||||
|
||||
import Modal from "~/app/_components/modal";
|
||||
|
||||
import { DeleteListConfirmation } from "./DeleteListConfirmation";
|
||||
import ListDropdown from "./ListDropdown";
|
||||
import { NewCardForm } from "./NewCardForm";
|
||||
import { NewListForm } from "./NewListForm";
|
||||
|
||||
@@ -210,15 +212,22 @@ export default function BoardPage() {
|
||||
<p className="mb-4 px-4 pt-1 text-sm font-medium text-dark-1000">
|
||||
{list.name}
|
||||
</p>
|
||||
<button
|
||||
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400"
|
||||
onClick={() => openNewCardForm(list.publicId)}
|
||||
>
|
||||
<HiOutlinePlusSmall
|
||||
className="h-5 w-5 text-dark-900"
|
||||
aria-hidden="true"
|
||||
<div>
|
||||
<button
|
||||
className="mx-1 inline-flex h-fit items-center rounded-md p-1 px-1 text-sm font-semibold text-dark-50 hover:bg-dark-400"
|
||||
onClick={() => openNewCardForm(list.publicId)}
|
||||
>
|
||||
<HiOutlinePlusSmall
|
||||
className="h-5 w-5 text-dark-900"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<ListDropdown
|
||||
setSelectedPublicListId={() =>
|
||||
setSelectedPublicListId(list.publicId)
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
||||
{(provided) => (
|
||||
@@ -283,6 +292,9 @@ export default function BoardPage() {
|
||||
</DragDropContext>
|
||||
</div>
|
||||
<Modal>
|
||||
{modalContentType === "DELETE_LIST" && (
|
||||
<DeleteListConfirmation listPublicId={selectedPublicListId} />
|
||||
)}
|
||||
{modalContentType === "NEW_CARD" && (
|
||||
<NewCardForm listPublicId={selectedPublicListId} />
|
||||
)}
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function RootLayout({
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className={`${jakarta.variable}`}>
|
||||
<body>
|
||||
<body className="h-screen overflow-hidden">
|
||||
<TRPCReactProvider headers={headers()}>
|
||||
<ModalProvider>
|
||||
<BoardProvider>{children}</BoardProvider>
|
||||
|
||||
Reference in New Issue
Block a user