* init: schema migration, isArchived added to board table. refactor: board repo for isArchived filtering * init: archived, unarchived API procedures. refactor: all query * fix: migration error * feat: add tabbed navigation for boards view * Implemented a Listbox for mobile and a tabbed navigation for desktop to switch between "Boards" and "Archived" views. * Introduced state management for active tab selection. * Updated UI components to reflect the new navigation structure. * init: frontend/boards lists & tabs * chore: fixed font styling and spacing * init:boardDropdown / boardView. * chore:added translations * Remove .cursor plan file from repo * fix:build erros * revert: remove locales changes * fix:reverted changes under locales, replaced the archive and unarchive endpoints. Reorder migrations * fix:migration issue * fix: update journal.json --------- Co-authored-by: Henry <henry_ball@hotmail.co.uk>
156 lines
4.0 KiB
TypeScript
156 lines
4.0 KiB
TypeScript
import { t } from "@lingui/core/macro";
|
|
import {
|
|
HiEllipsisHorizontal,
|
|
HiLink,
|
|
HiOutlineDocumentDuplicate,
|
|
HiOutlineTrash,
|
|
HiOutlineStar,
|
|
HiStar,
|
|
} from "react-icons/hi2";
|
|
import { IoArchiveOutline } from "react-icons/io5";
|
|
import Dropdown from "~/components/Dropdown";
|
|
import { usePermissions } from "~/hooks/usePermissions";
|
|
import { useModal } from "~/providers/modal";
|
|
import { usePopup } from "~/providers/popup";
|
|
import { api } from "~/utils/api";
|
|
|
|
export default function BoardDropdown({
|
|
isTemplate,
|
|
isLoading,
|
|
isArchived,
|
|
boardPublicId,
|
|
isFavorite,
|
|
boardName,
|
|
}: {
|
|
isTemplate: boolean;
|
|
isLoading: boolean;
|
|
boardPublicId: string;
|
|
isArchived?: boolean;
|
|
isFavorite?: boolean;
|
|
boardName?: string;
|
|
}) {
|
|
const { openModal } = useModal();
|
|
const { showPopup } = usePopup();
|
|
const { canEditBoard, canDeleteBoard, canCreateBoard, canArchiveBoard } =
|
|
usePermissions();
|
|
const utils = api.useUtils();
|
|
|
|
const updateBoard = api.board.update.useMutation({
|
|
onSuccess: (_data, variables) => {
|
|
void utils.board.all.invalidate();
|
|
void utils.board.byId.invalidate();
|
|
if (variables.isArchived !== undefined) {
|
|
showPopup({
|
|
header: variables.isArchived ? t`Board archived` : t`Board unarchived`,
|
|
message: variables.isArchived
|
|
? t`The board has been archived.`
|
|
: t`The board has been unarchived.`,
|
|
icon: "success",
|
|
});
|
|
} else if (variables.favorite !== undefined) {
|
|
showPopup({
|
|
header: variables.favorite
|
|
? t`Added to favorites`
|
|
: t`Removed from favorites`,
|
|
message: variables.favorite
|
|
? t`${boardName ?? "Board"} has been added to your favorites.`
|
|
: t`${boardName ?? "Board"} has been removed from your favorites.`,
|
|
icon: "success",
|
|
});
|
|
}
|
|
},
|
|
onError: () => {
|
|
showPopup({
|
|
header: t`Unable to update board`,
|
|
message: t`Please try again later, or contact customer support.`,
|
|
icon: "error",
|
|
});
|
|
},
|
|
});
|
|
|
|
const handleToggleFavorite = () => {
|
|
updateBoard.mutate({
|
|
boardPublicId,
|
|
favorite: !isFavorite,
|
|
});
|
|
};
|
|
|
|
const handleArchiveOrUnarchive = () => {
|
|
updateBoard.mutate({
|
|
boardPublicId,
|
|
isArchived: !isArchived,
|
|
});
|
|
};
|
|
|
|
const isArchiveActionPending = updateBoard.isPending;
|
|
|
|
const items = [
|
|
...(isTemplate && canCreateBoard
|
|
? [
|
|
{
|
|
label: t`Make template`,
|
|
action: () => openModal("CREATE_TEMPLATE"),
|
|
icon: (
|
|
<HiOutlineDocumentDuplicate className="h-[16px] w-[16px] text-dark-900" />
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
...(!isTemplate && canEditBoard
|
|
? [
|
|
{
|
|
label: t`Edit board URL`,
|
|
action: () => openModal("UPDATE_BOARD_SLUG"),
|
|
icon: <HiLink className="h-[16px] w-[16px] text-dark-900" />,
|
|
},
|
|
]
|
|
: []),
|
|
...(!isTemplate && canArchiveBoard
|
|
? [
|
|
{
|
|
label: isArchived ? t`Unarchive board` : t`Archive board`,
|
|
action: handleArchiveOrUnarchive,
|
|
icon: (
|
|
<IoArchiveOutline className="h-[16px] w-[16px] text-dark-900" />
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
{
|
|
label: isFavorite
|
|
? t`Remove from favorites`
|
|
: t`Add to favorites`,
|
|
action: handleToggleFavorite,
|
|
icon: isFavorite ? (
|
|
<HiStar className="h-[16px] w-[16px] text-dark-900" />
|
|
) : (
|
|
<HiOutlineStar className="h-[16px] w-[16px] text-dark-900" />
|
|
),
|
|
},
|
|
...(canDeleteBoard
|
|
? [
|
|
{
|
|
label: isTemplate ? t`Delete template` : t`Delete board`,
|
|
action: () => openModal("DELETE_BOARD"),
|
|
icon: (
|
|
<HiOutlineTrash className="h-[16px] w-[16px] text-dark-900" />
|
|
),
|
|
},
|
|
]
|
|
: []),
|
|
];
|
|
|
|
if (items.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Dropdown
|
|
disabled={isLoading || isArchiveActionPending}
|
|
items={items}
|
|
>
|
|
<HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
|
|
</Dropdown>
|
|
);
|
|
}
|