feat: empty boards and lists state

This commit is contained in:
Henry
2025-02-21 09:10:27 +00:00
parent cf31c50f46
commit 3608ec0e31
3 changed files with 126 additions and 80 deletions

View File

@@ -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"}>

View File

@@ -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">

View File

@@ -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>