import Link from "next/link"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import ContentEditable from "react-contenteditable"; import { useForm } from "react-hook-form"; import { IoChevronForwardSharp } from "react-icons/io5"; import type { GetCardByIdOutput } from "@kan/api/types"; import Avatar from "~/components/Avatar"; import LabelIcon from "~/components/LabelIcon"; import Modal from "~/components/modal"; import { NewWorkspaceForm } from "~/components/NewWorkspaceForm"; import { PageHead } from "~/components/PageHead"; import { useModal } from "~/providers/modal"; import { usePopup } from "~/providers/popup"; import { api } from "~/utils/api"; import { formatMemberDisplayName } from "~/utils/helpers"; import { getPublicUrl } from "~/utils/supabase/getPublicUrl"; import ActivityList from "./components/ActivityList"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; import { DeleteLabelConfirmation } from "./components/DeleteLabelConfirmation"; import Dropdown from "./components/Dropdown"; import { LabelForm } from "./components/LabelForm"; import LabelSelector from "./components/LabelSelector"; import ListSelector from "./components/ListSelector"; import MemberSelector from "./components/MemberSelector"; import NewCommentForm from "./components/NewCommentForm"; interface FormValues { cardId: string; title: string; description: string; } export default function CardPage() { const router = useRouter(); const utils = api.useUtils(); const { modalContentType, entityId } = useModal(); const { showPopup } = usePopup(); const [card, setCard] = useState(); const cardId = Array.isArray(router.query.cardId) ? router.query.cardId[0] : router.query.cardId; const { data, isLoading, refetch } = api.card.byId.useQuery({ cardPublicId: cardId ?? "", }); const refetchCard = async () => { try { const { data: updatedCard } = await refetch(); if (updatedCard) setCard(updatedCard); } catch (error) { console.error({ error }); } }; useEffect(() => { setCard(data); }, [data]); const board = card?.list?.board; const boardId = board?.publicId; const labels = board?.labels; const activities = card?.activities; const workspaceMembers = board?.workspace?.members; const selectedLabels = card?.labels; const selectedMembers = card?.members; const handleChangeList = (newListPublicId: string) => { if (!card) return; setCard({ ...card, list: { ...card.list, publicId: newListPublicId, name: card.list?.name ?? "", board: card.list?.board ?? null, }, }); }; const handleSelectLabel = (labelPublicId: string) => { if (!card) return; const isSelected = card.labels.some( (label) => label.publicId === labelPublicId, ); const updatedLabels = isSelected ? card.labels.filter((label) => label.publicId !== labelPublicId) : [ ...(card.labels ?? []), labels?.find((label) => label.publicId === labelPublicId), ].filter(Boolean); setCard({ ...card, labels: updatedLabels as { publicId: string; name: string; colourCode: string | null; }[], }); }; const handleSelectMember = (memberPublicId: string) => { if (!card) return; const isSelected = card.members.some( (member) => member.publicId === memberPublicId, ); const updatedMembers = isSelected ? card.members.filter((member) => member.publicId !== memberPublicId) : [ ...(card.members ?? []), workspaceMembers?.find( (member) => member.publicId === memberPublicId, ), ]; setCard({ ...card, members: updatedMembers.filter(Boolean) as { publicId: string; user: { id: string; name: string | null; email: string; image: string | null; } | null; }[], }); }; const formattedLabels = labels?.map((label) => { const isSelected = selectedLabels?.some( (selectedLabel) => selectedLabel.publicId === label.publicId, ); return { key: label.publicId, value: label.name, selected: isSelected ?? false, leftIcon: , }; }) ?? []; const formattedLists = board?.lists.map((list) => ({ key: list.publicId, value: list.name, selected: list.publicId === card?.list?.publicId, })) ?? []; const formattedMembers = workspaceMembers?.map((member) => { const isSelected = selectedMembers?.some( (assignedMember) => assignedMember.publicId === member.publicId, ); return { key: member.publicId, value: formatMemberDisplayName( member.user?.name ?? null, member.user?.email ?? null, ), imageUrl: member.user?.image ? getPublicUrl(member.user.image) : undefined, selected: isSelected ?? false, leftIcon: ( ), }; }) ?? []; const updateCard = api.card.update.useMutation({ onSuccess: async () => { await refetchCard(); }, onError: async () => { await refetchCard(); showPopup({ header: "Unable to update card", message: "Please try again later, or contact customer support.", icon: "error", }); }, }); const { register, handleSubmit, setValue, watch } = useForm({ values: { cardId: cardId ?? "", title: data?.title ?? "", description: data?.description ?? "", }, }); const onSubmit = (values: FormValues) => { updateCard.mutate({ cardPublicId: values.cardId, title: values.title, description: values.description, }); }; if (!cardId) return <>; return ( <>
{isLoading ? (
) : ( <> {board?.name}
)}
setValue("description", e.target.value)} onBlur={handleSubmit(onSubmit)} className="block w-full border-0 bg-transparent py-1.5 text-light-900 focus-visible:outline-none dark:text-dark-1000 sm:text-sm sm:leading-6" />

Activity

List

Labels

Members

{modalContentType === "NEW_LABEL" && ( )} {modalContentType === "EDIT_LABEL" && ( )} {modalContentType === "DELETE_LABEL" && ( )} {modalContentType === "DELETE_CARD" && ( )} {modalContentType === "NEW_WORKSPACE" && }
); }