feat: empty boards and lists state
This commit is contained in:
@@ -5,7 +5,7 @@ import { useRouter } from "next/router";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { DragDropContext, Draggable } from "react-beautiful-dnd";
|
import { DragDropContext, Draggable } from "react-beautiful-dnd";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { HiOutlinePlusSmall } from "react-icons/hi2";
|
import { HiOutlinePlusSmall, HiOutlineSquare3Stack3D } from "react-icons/hi2";
|
||||||
|
|
||||||
import type { UpdateBoardInput } from "@kan/api/types";
|
import type { UpdateBoardInput } from "@kan/api/types";
|
||||||
|
|
||||||
@@ -274,83 +274,111 @@ export default function BoardPage() {
|
|||||||
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
|
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<>
|
||||||
<Droppable
|
{boardData?.lists.length === 0 ? (
|
||||||
droppableId="all-lists"
|
<div className="z-10 flex h-full w-full flex-col items-center justify-center space-y-8 pb-[150px]">
|
||||||
direction="horizontal"
|
<div className="flex flex-col items-center">
|
||||||
type="LIST"
|
<HiOutlineSquare3Stack3D className="h-10 w-10 text-light-800 dark:text-dark-800" />
|
||||||
>
|
<p className="mb-2 mt-4 text-[14px] font-bold text-light-1000 dark:text-dark-950">
|
||||||
{(provided) => (
|
No lists
|
||||||
<div
|
</p>
|
||||||
className="flex"
|
<p className="text-[14px] text-light-900 dark:text-dark-900">
|
||||||
ref={provided.innerRef}
|
Get started by creating a new list
|
||||||
{...provided.droppableProps}
|
</p>
|
||||||
>
|
|
||||||
<div className="min-w-[2rem]" />
|
|
||||||
{boardData?.lists.map((list, index) => (
|
|
||||||
<List
|
|
||||||
index={index}
|
|
||||||
key={index}
|
|
||||||
list={list}
|
|
||||||
setSelectedPublicListId={(publicListId) =>
|
|
||||||
setSelectedPublicListId(publicListId)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
|
||||||
{(provided) => (
|
|
||||||
<div
|
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.droppableProps}
|
|
||||||
className="scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px] z-10 h-full max-h-[calc(100vh-265px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar scrollbar-track-dark-100 scrollbar-thumb-dark-600"
|
|
||||||
>
|
|
||||||
{list.cards.map((card, index) => (
|
|
||||||
<Draggable
|
|
||||||
key={card.publicId}
|
|
||||||
draggableId={card.publicId}
|
|
||||||
index={index}
|
|
||||||
>
|
|
||||||
{(provided) => (
|
|
||||||
<Link
|
|
||||||
onClick={(e) => {
|
|
||||||
if (
|
|
||||||
card.publicId.startsWith(
|
|
||||||
"PLACEHOLDER",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
e.preventDefault();
|
|
||||||
}}
|
|
||||||
key={card.publicId}
|
|
||||||
href={`/cards/${card.publicId}`}
|
|
||||||
className={`mb-2 flex !cursor-pointer flex-col ${
|
|
||||||
card.publicId.startsWith("PLACEHOLDER")
|
|
||||||
? "pointer-events-none"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.draggableProps}
|
|
||||||
{...provided.dragHandleProps}
|
|
||||||
>
|
|
||||||
<Card
|
|
||||||
title={card.title}
|
|
||||||
labels={card.labels}
|
|
||||||
members={card.members}
|
|
||||||
/>
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</List>
|
|
||||||
))}
|
|
||||||
<div className="min-w-[0.75rem]" />
|
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<Button
|
||||||
</Droppable>
|
onClick={() => {
|
||||||
</DragDropContext>
|
if (boardId) openNewListForm(boardId);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create new list
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
|
<Droppable
|
||||||
|
droppableId="all-lists"
|
||||||
|
direction="horizontal"
|
||||||
|
type="LIST"
|
||||||
|
>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
className="flex"
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}
|
||||||
|
>
|
||||||
|
<div className="min-w-[2rem]" />
|
||||||
|
{boardData?.lists.map((list, index) => (
|
||||||
|
<List
|
||||||
|
index={index}
|
||||||
|
key={index}
|
||||||
|
list={list}
|
||||||
|
setSelectedPublicListId={(publicListId) =>
|
||||||
|
setSelectedPublicListId(publicListId)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Droppable
|
||||||
|
droppableId={`${list.publicId}`}
|
||||||
|
type="CARD"
|
||||||
|
>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}
|
||||||
|
className="scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px] z-10 h-full max-h-[calc(100vh-265px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar scrollbar-track-dark-100 scrollbar-thumb-dark-600"
|
||||||
|
>
|
||||||
|
{list.cards.map((card, index) => (
|
||||||
|
<Draggable
|
||||||
|
key={card.publicId}
|
||||||
|
draggableId={card.publicId}
|
||||||
|
index={index}
|
||||||
|
>
|
||||||
|
{(provided) => (
|
||||||
|
<Link
|
||||||
|
onClick={(e) => {
|
||||||
|
if (
|
||||||
|
card.publicId.startsWith(
|
||||||
|
"PLACEHOLDER",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
key={card.publicId}
|
||||||
|
href={`/cards/${card.publicId}`}
|
||||||
|
className={`mb-2 flex !cursor-pointer flex-col ${
|
||||||
|
card.publicId.startsWith(
|
||||||
|
"PLACEHOLDER",
|
||||||
|
)
|
||||||
|
? "pointer-events-none"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
>
|
||||||
|
<Card
|
||||||
|
title={card.title}
|
||||||
|
labels={card.labels}
|
||||||
|
members={card.members}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
))}
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</List>
|
||||||
|
))}
|
||||||
|
<div className="min-w-[0.75rem]" />
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Modal modalSize={modalContentType === "NEW_CARD" ? "md" : "sm"}>
|
<Modal modalSize={modalContentType === "NEW_CARD" ? "md" : "sm"}>
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { HiOutlineRectangleStack } from "react-icons/hi2";
|
||||||
|
|
||||||
|
import Button from "~/components/Button";
|
||||||
import PatternedBackground from "~/components/PatternedBackground";
|
import PatternedBackground from "~/components/PatternedBackground";
|
||||||
|
import { useModal } from "~/providers/modal";
|
||||||
import { useWorkspace } from "~/providers/workspace";
|
import { useWorkspace } from "~/providers/workspace";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
export function BoardsList() {
|
export function BoardsList() {
|
||||||
const { workspace } = useWorkspace();
|
const { workspace } = useWorkspace();
|
||||||
|
const { openModal } = useModal();
|
||||||
|
|
||||||
const { data, isLoading } = api.board.all.useQuery(
|
const { data, isLoading } = api.board.all.useQuery(
|
||||||
{ workspacePublicId: workspace.publicId },
|
{ workspacePublicId: workspace.publicId },
|
||||||
@@ -21,7 +25,21 @@ export function BoardsList() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (data?.length === 0) return <></>;
|
if (data?.length === 0)
|
||||||
|
return (
|
||||||
|
<div className="z-10 flex h-full w-full flex-col items-center justify-center space-y-8 pb-[150px]">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<HiOutlineRectangleStack className="h-10 w-10 text-light-800 dark:text-dark-800" />
|
||||||
|
<p className="mb-2 mt-4 text-[14px] font-bold text-light-1000 dark:text-dark-950">
|
||||||
|
No boards
|
||||||
|
</p>
|
||||||
|
<p className="text-[14px] text-light-900 dark:text-dark-900">
|
||||||
|
Get started by creating a new board
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button onClick={() => openModal("NEW_BOARD")}>Create new board</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xxl:grid-cols-5">
|
<div className="grid w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xxl:grid-cols-5">
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function BoardsPage() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={`Boards | ${workspace.name ?? "Workspace"}`} />
|
<PageHead title={`Boards | ${workspace.name ?? "Workspace"}`} />
|
||||||
<div className="p-8">
|
<div className="h-full p-8">
|
||||||
<div className="mb-8 flex w-full justify-between">
|
<div className="mb-8 flex w-full justify-between">
|
||||||
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
|
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
|
||||||
Boards
|
Boards
|
||||||
@@ -57,7 +57,7 @@ export default function BoardsPage() {
|
|||||||
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
|
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<div className="flex flex-row">
|
<div className="flex h-full flex-row">
|
||||||
<BoardsList />
|
<BoardsList />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user