feat: skeleton loaders
This commit is contained in:
@@ -64,7 +64,7 @@ export default function List({
|
|||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.draggableProps}
|
{...provided.draggableProps}
|
||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
className="dark-text-dark-1000 mr-5 h-fit min-w-[18rem] max-w-[18rem] rounded-md border border-light-400 bg-light-300 py-2 pl-2 pr-1 text-neutral-900 dark:border-dark-400 dark:bg-dark-200"
|
className="dark-text-dark-1000 mr-5 h-fit min-w-[18rem] max-w-[18rem] rounded-md border border-light-400 bg-light-300 py-2 pl-2 pr-1 text-neutral-900 dark:border-dark-300 dark:bg-dark-100"
|
||||||
>
|
>
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<form
|
<form
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ export default function BoardPage() {
|
|||||||
const [selectedPublicListId, setSelectedPublicListId] =
|
const [selectedPublicListId, setSelectedPublicListId] =
|
||||||
useState<PublicListId>("");
|
useState<PublicListId>("");
|
||||||
|
|
||||||
console.log({ boardData });
|
|
||||||
|
|
||||||
const boardId = params?.boardId?.length ? params.boardId[0] : null;
|
const boardId = params?.boardId?.length ? params.boardId[0] : null;
|
||||||
|
|
||||||
const updateBoard = api.board.update.useMutation();
|
const updateBoard = api.board.update.useMutation();
|
||||||
@@ -86,7 +84,7 @@ export default function BoardPage() {
|
|||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data, isSuccess } = api.board.byId.useQuery(
|
const { data, isSuccess, isLoading } = api.board.byId.useQuery(
|
||||||
{ id: boardId ?? "" },
|
{ id: boardId ?? "" },
|
||||||
{
|
{
|
||||||
enabled: !!boardId,
|
enabled: !!boardId,
|
||||||
@@ -94,7 +92,6 @@ export default function BoardPage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (isSuccess && data) {
|
if (isSuccess && data) {
|
||||||
console.log({ data });
|
|
||||||
setBoardData(data);
|
setBoardData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,20 +194,27 @@ export default function BoardPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="z-20 flex w-full justify-between p-8 ">
|
<div className="z-20 flex w-full justify-between p-8 ">
|
||||||
<form
|
{isLoading ? (
|
||||||
onSubmit={formik.handleSubmit}
|
<div className="flex space-x-2">
|
||||||
className="focus-visible:outline-none"
|
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-200" />
|
||||||
>
|
</div>
|
||||||
<input
|
) : (
|
||||||
type="name"
|
<form
|
||||||
id="name"
|
onSubmit={formik.handleSubmit}
|
||||||
name="name"
|
className="focus-visible:outline-none"
|
||||||
value={formik.values.name}
|
>
|
||||||
onChange={formik.handleChange}
|
<input
|
||||||
onBlur={formik.submitForm}
|
type="name"
|
||||||
className="block border-0 bg-transparent p-0 py-0 font-medium leading-[2.3rem] tracking-tight text-neutral-900 focus:ring-0 focus-visible:outline-none dark:text-dark-1000 sm:text-[1.2rem]"
|
id="name"
|
||||||
/>
|
name="name"
|
||||||
</form>
|
value={formik.values.name}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.submitForm}
|
||||||
|
className="block border-0 bg-transparent p-0 py-0 font-medium leading-[2.3rem] tracking-tight text-neutral-900 focus:ring-0 focus-visible:outline-none dark:text-dark-1000 sm:text-[1.2rem]"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -228,103 +232,115 @@ export default function BoardPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="scrollbar-w-none z-10 flex-1 overflow-y-hidden overflow-x-scroll overscroll-contain pb-5 scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300">
|
<div className="scrollbar-w-none z-10 flex-1 overflow-y-hidden overflow-x-scroll overscroll-contain pb-5 scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300">
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
{isLoading ? (
|
||||||
<Droppable droppableId="all-lists" direction="horizontal" type="LIST">
|
<div className="ml-[2rem] flex">
|
||||||
{(provided) => (
|
<div className="0 mr-5 h-[500px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
<div
|
<div className="0 mr-5 h-[275px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
className="flex"
|
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
ref={provided.innerRef}
|
</div>
|
||||||
{...provided.droppableProps}
|
) : (
|
||||||
>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<div className="min-w-[2rem]" />
|
<Droppable
|
||||||
{boardData?.lists?.map((list: List, index) => (
|
droppableId="all-lists"
|
||||||
<List
|
direction="horizontal"
|
||||||
index={index}
|
type="LIST"
|
||||||
key={index}
|
>
|
||||||
list={list}
|
{(provided) => (
|
||||||
setSelectedPublicListId={(publicListId) =>
|
<div
|
||||||
setSelectedPublicListId(publicListId)
|
className="flex"
|
||||||
}
|
ref={provided.innerRef}
|
||||||
>
|
{...provided.droppableProps}
|
||||||
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
>
|
||||||
{(provided) => (
|
<div className="min-w-[2rem]" />
|
||||||
<div
|
{boardData?.lists?.map((list: List, index) => (
|
||||||
ref={provided.innerRef}
|
<List
|
||||||
{...provided.droppableProps}
|
index={index}
|
||||||
className="h-full max-h-[calc(100vh-250px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar scrollbar-track-dark-100 scrollbar-thumb-dark-600 scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px]"
|
key={index}
|
||||||
>
|
list={list}
|
||||||
{list.cards?.map((card, index) => (
|
setSelectedPublicListId={(publicListId) =>
|
||||||
<Draggable
|
setSelectedPublicListId(publicListId)
|
||||||
key={card.publicId}
|
}
|
||||||
draggableId={card.publicId}
|
>
|
||||||
index={index}
|
<Droppable droppableId={`${list.publicId}`} type="CARD">
|
||||||
>
|
{(provided) => (
|
||||||
{(provided) => (
|
<div
|
||||||
<Link
|
ref={provided.innerRef}
|
||||||
key={card.publicId}
|
{...provided.droppableProps}
|
||||||
href={`/cards/${card.publicId}`}
|
className="h-full max-h-[calc(100vh-250px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar scrollbar-track-dark-100 scrollbar-thumb-dark-600 scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px]"
|
||||||
className="mb-2 flex !cursor-pointer flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-500 dark:text-dark-1000"
|
>
|
||||||
ref={provided.innerRef}
|
{list.cards?.map((card, index) => (
|
||||||
{...provided.draggableProps}
|
<Draggable
|
||||||
{...provided.dragHandleProps}
|
key={card.publicId}
|
||||||
>
|
draggableId={card.publicId}
|
||||||
<div>{card.title}</div>
|
index={index}
|
||||||
{(card.labels?.length ?? 0) ||
|
>
|
||||||
(card.members?.length ?? 0) ? (
|
{(provided) => (
|
||||||
<div className="mt-2 flex justify-end space-x-1">
|
<Link
|
||||||
{card.labels?.map((label) => (
|
key={card.publicId}
|
||||||
<span
|
href={`/cards/${card.publicId}`}
|
||||||
key={label.publicId}
|
className="mb-2 flex !cursor-pointer flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-300 dark:text-dark-1000 dark:hover:bg-dark-400"
|
||||||
className="inline-flex w-fit items-center gap-x-1.5 rounded-full px-2 py-1 text-[10px] font-medium text-neutral-600 ring-1 ring-inset ring-light-600 dark:text-dark-1000 dark:ring-dark-800"
|
ref={provided.innerRef}
|
||||||
>
|
{...provided.draggableProps}
|
||||||
<svg
|
{...provided.dragHandleProps}
|
||||||
fill={label.colourCode}
|
>
|
||||||
className="h-2 w-2"
|
<div>{card.title}</div>
|
||||||
viewBox="0 0 6 6"
|
{(card.labels?.length ?? 0) ||
|
||||||
aria-hidden="true"
|
(card.members?.length ?? 0) ? (
|
||||||
>
|
<div className="mt-2 flex justify-end space-x-1">
|
||||||
<circle cx={3} cy={3} r={3} />
|
{card.labels?.map((label) => (
|
||||||
</svg>
|
|
||||||
<div>{label.name}</div>
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
<div className="isolate flex -space-x-1 overflow-hidden">
|
|
||||||
{card.members?.map((member) => (
|
|
||||||
<span
|
<span
|
||||||
key={member.publicId}
|
key={label.publicId}
|
||||||
className="inline-flex h-6 w-6 items-center justify-center rounded-full bg-light-900 ring-2 ring-light-50 dark:bg-gray-500 dark:ring-dark-500"
|
className="inline-flex w-fit items-center gap-x-1.5 rounded-full px-2 py-1 text-[10px] font-medium text-neutral-600 ring-1 ring-inset ring-light-600 dark:text-dark-1000 dark:ring-dark-800"
|
||||||
>
|
>
|
||||||
<span className="text-[10px] font-medium leading-none text-white">
|
<svg
|
||||||
{member.user.name
|
fill={label.colourCode}
|
||||||
.split(" ")
|
className="h-2 w-2"
|
||||||
.map((namePart) =>
|
viewBox="0 0 6 6"
|
||||||
namePart
|
aria-hidden="true"
|
||||||
.charAt(0)
|
>
|
||||||
.toUpperCase(),
|
<circle cx={3} cy={3} r={3} />
|
||||||
)
|
</svg>
|
||||||
.join("")}
|
<div>{label.name}</div>
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
|
<div className="isolate flex -space-x-1 overflow-hidden">
|
||||||
|
{card.members?.map((member) => (
|
||||||
|
<span
|
||||||
|
key={member.publicId}
|
||||||
|
className="inline-flex h-6 w-6 items-center justify-center rounded-full bg-light-900 ring-2 ring-light-50 dark:bg-gray-500 dark:ring-dark-500"
|
||||||
|
>
|
||||||
|
<span className="text-[10px] font-medium leading-none text-white">
|
||||||
|
{member.user.name
|
||||||
|
.split(" ")
|
||||||
|
.map((namePart) =>
|
||||||
|
namePart
|
||||||
|
.charAt(0)
|
||||||
|
.toUpperCase(),
|
||||||
|
)
|
||||||
|
.join("")}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : null}
|
||||||
) : null}
|
</Link>
|
||||||
</Link>
|
)}
|
||||||
)}
|
</Draggable>
|
||||||
</Draggable>
|
))}
|
||||||
))}
|
{provided.placeholder}
|
||||||
{provided.placeholder}
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</Droppable>
|
||||||
</Droppable>
|
</List>
|
||||||
</List>
|
))}
|
||||||
))}
|
<div className="min-w-[0.75rem]" />
|
||||||
<div className="min-w-[0.75rem]" />
|
{provided.placeholder}
|
||||||
{provided.placeholder}
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
</Droppable>
|
||||||
</Droppable>
|
</DragDropContext>
|
||||||
</DragDropContext>
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Modal>
|
<Modal>
|
||||||
{modalContentType === "DELETE_BOARD" && <DeleteBoardConfirmation />}
|
{modalContentType === "DELETE_BOARD" && <DeleteBoardConfirmation />}
|
||||||
|
|||||||
@@ -6,11 +6,20 @@ import { useWorkspace } from "~/providers/workspace";
|
|||||||
export function BoardsList() {
|
export function BoardsList() {
|
||||||
const { workspace } = useWorkspace();
|
const { workspace } = useWorkspace();
|
||||||
|
|
||||||
const { data } = api.board.all.useQuery(
|
const { data, isLoading } = api.board.all.useQuery(
|
||||||
{ workspacePublicId: workspace?.publicId },
|
{ workspacePublicId: workspace?.publicId },
|
||||||
{ enabled: workspace?.publicId ? true : false },
|
{ enabled: workspace?.publicId ? true : false },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isLoading)
|
||||||
|
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="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
|
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
|
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
if (data?.length === 0) return <></>;
|
if (data?.length === 0) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export default function CardPage() {
|
|||||||
? params.cardId[0]
|
? params.cardId[0]
|
||||||
: params?.cardId;
|
: params?.cardId;
|
||||||
|
|
||||||
const { data, error } = api.card.byId.useQuery({ id: cardId ?? "" });
|
const { data, isLoading } = api.card.byId.useQuery({ id: cardId ?? "" });
|
||||||
|
|
||||||
const board = data?.list?.board;
|
const board = data?.list?.board;
|
||||||
const boardId = board?.publicId;
|
const boardId = board?.publicId;
|
||||||
@@ -40,8 +40,6 @@ export default function CardPage() {
|
|||||||
const selectedLabels = data?.labels;
|
const selectedLabels = data?.labels;
|
||||||
const selectedMembers = data?.members;
|
const selectedMembers = data?.members;
|
||||||
|
|
||||||
console.log({ board: error });
|
|
||||||
|
|
||||||
const formattedLabels =
|
const formattedLabels =
|
||||||
labels?.map((label) => {
|
labels?.map((label) => {
|
||||||
const isSelected = selectedLabels?.some(
|
const isSelected = selectedLabels?.some(
|
||||||
@@ -98,32 +96,41 @@ export default function CardPage() {
|
|||||||
<div className="flex h-full flex-1 flex-row">
|
<div className="flex h-full flex-1 flex-row">
|
||||||
<div className="w-full p-8">
|
<div className="w-full p-8">
|
||||||
<div className="mb-8 flex w-full items-center justify-between">
|
<div className="mb-8 flex w-full items-center justify-between">
|
||||||
<Link
|
{isLoading ? (
|
||||||
className="whitespace-nowrap font-medium leading-[2.3rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1.2rem]"
|
<div className="flex space-x-2">
|
||||||
href={`/boards/${board?.publicId}`}
|
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
|
||||||
>
|
<div className="h-[2.3rem] w-[300px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
|
||||||
{board?.name}
|
|
||||||
</Link>
|
|
||||||
<IoChevronForwardSharp
|
|
||||||
size={18}
|
|
||||||
className="mx-2 text-light-900 dark:text-dark-900"
|
|
||||||
/>
|
|
||||||
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="title"
|
|
||||||
name="title"
|
|
||||||
value={formik.values.title}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.submitForm}
|
|
||||||
className="block w-full border-0 bg-transparent p-0 py-0 font-medium tracking-tight text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
) : (
|
||||||
<div className="flex">
|
<>
|
||||||
<Dropdown />
|
<Link
|
||||||
</div>
|
className="whitespace-nowrap font-medium leading-[2.3rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1.2rem]"
|
||||||
|
href={`/boards/${board?.publicId}`}
|
||||||
|
>
|
||||||
|
{board?.name}
|
||||||
|
</Link>
|
||||||
|
<IoChevronForwardSharp
|
||||||
|
size={18}
|
||||||
|
className="mx-2 text-light-900 dark:text-dark-900"
|
||||||
|
/>
|
||||||
|
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
name="title"
|
||||||
|
value={formik.values.title}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.submitForm}
|
||||||
|
className="block w-full border-0 bg-transparent p-0 py-0 font-medium tracking-tight text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div className="flex">
|
||||||
|
<Dropdown />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-8 flex w-full max-w-2xl justify-between">
|
<div className="mb-8 flex w-full max-w-2xl justify-between">
|
||||||
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
|
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
|
||||||
|
|||||||
Reference in New Issue
Block a user