feat: update card and title description

This commit is contained in:
Henry
2023-11-28 22:36:31 +00:00
parent 1ff7f9b9c0
commit 143245eaf8
8 changed files with 5656 additions and 66 deletions

5596
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@
"next-auth": "^4.24.4", "next-auth": "^4.24.4",
"react": "18.2.0", "react": "18.2.0",
"react-beautiful-dnd": "^13.1.1", "react-beautiful-dnd": "^13.1.1",
"react-contenteditable": "^3.3.7",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-icons": "^4.11.0", "react-icons": "^4.11.0",
"react-lottie-player": "^1.5.5", "react-lottie-player": "^1.5.5",

View File

@@ -125,7 +125,7 @@ export default function BoardPage() {
className="-mr-0.5 h-5 w-5" className="-mr-0.5 h-5 w-5"
aria-hidden="true" aria-hidden="true"
/> />
New New list
</button> </button>
</div> </div>
</div> </div>

View File

@@ -8,7 +8,7 @@ export function Boards() {
if (data?.length === 0) return <></>; if (data?.length === 0) return <></>;
return ( return (
<div> <>
{data?.map((board) => { {data?.map((board) => {
return ( return (
<Link key={board.publicId} href={`boards/${board.publicId}`}> <Link key={board.publicId} href={`boards/${board.publicId}`}>
@@ -20,6 +20,6 @@ export function Boards() {
</Link> </Link>
); );
})} })}
</div> </>
); );
} }

View File

@@ -1,84 +1,75 @@
"use client"; "use client";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { HiOutlinePlusSmall } from "react-icons/hi2"; import { useFormik } from "formik";
import { Formik, Form, Field, type FieldProps } from "formik"; import ContentEditable from "react-contenteditable";
import { api } from "~/trpc/react"; import { api } from "~/trpc/react";
interface FormValues { interface FormValues {
cardId: string; cardId: string;
title: string;
description: string; description: string;
} }
export default function CardPage() { export default function CardPage() {
const params = useParams(); const params = useParams();
const cardId = params?.id?.length && params.id[0]; const cardId = params?.id?.length ? params.id[0] : null;
const { data } = api.card.byId.useQuery({ id: cardId ?? "" });
const updateCard = api.card.update.useMutation();
const formik = useFormik({
initialValues: {
cardId: cardId ?? "",
title: data?.title ? data.title : "",
description: data?.description ? data.description : "",
},
onSubmit: (values: FormValues) => {
updateCard.mutate({
cardId: values.cardId,
title: values.title,
description: values.description,
});
},
enableReinitialize: true,
});
if (!cardId) return <></>; if (!cardId) return <></>;
const { data } = api.card.byId.useQuery({ id: cardId });
const updateCard = api.card.updateDescription.useMutation();
return ( return (
<div> <div>
<div className="mb-8 flex w-full justify-between"> <div className="mb-8 flex w-full justify-between">
<h1 className="font-medium tracking-tight text-dark-1000 sm:text-[1.2rem]"> <form onSubmit={formik.handleSubmit} className="w-full space-y-6">
{data?.title} <div className="mt-2">
</h1> <input
<div> type="text"
<button id="title"
type="button" name="title"
className="inline-flex items-center gap-x-1.5 rounded-md bg-dark-1000 px-3 py-2 text-sm font-semibold text-dark-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" value={formik.values.title}
> onChange={formik.handleChange}
<HiOutlinePlusSmall onBlur={formik.submitForm}
className="-mr-0.5 h-5 w-5" className="block w-full border-0 bg-transparent p-0 py-1.5 font-medium tracking-tight text-dark-1000 focus:ring-0 sm:text-[1.2rem] sm:leading-6"
aria-hidden="true"
/> />
New </div>
</button> </form>
</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">
<Formik <form onSubmit={formik.handleSubmit} className="w-full space-y-6">
initialValues={{ <div className="mt-2">
cardId, <ContentEditable
description: data?.description ? data.description : "", html={formik.values.description || "Add description..."}
}} disabled={false}
onSubmit={(values: FormValues) => { onChange={(e) =>
updateCard.mutate({ formik.setFieldValue("description", e.target.value)
cardId: values.cardId, }
description: values.description, onBlur={formik.submitForm}
}); className="block w-full border-0 bg-transparent py-1.5 text-dark-1000 focus-visible:outline-none sm:text-sm sm:leading-6"
}} />
enableReinitialize </div>
> </form>
<Form className="w-full space-y-6">
<div>
<div className="mt-2">
<Field
id="description"
name="description"
render={({ field, form }: FieldProps) => (
<div
onBlur={() => form.submitForm()}
onInput={async (e) => {
const { innerText } = e.target as HTMLDivElement;
await form.setFieldValue("description", innerText);
}}
contentEditable
className="block w-full border-0 bg-transparent py-1.5 text-dark-1000 focus-visible:outline-none sm:text-sm sm:leading-6"
>
{field.value || "Add description..."}
</div>
)}
/>
</div>
</div>
</Form>
</Formik>
</div> </div>
</div> </div>
); );

View File

@@ -67,7 +67,7 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({
const refetchBoard = () => const refetchBoard = () =>
utils.board.byId.refetch({ id: boardData.publicId }); utils.board.byId.refetch({ id: boardData.publicId });
const updateCardMutation = api.card.update.useMutation({ const updateCardMutation = api.card.reorder.useMutation({
onSuccess: async () => { onSuccess: async () => {
try { try {
await refetchBoard(); await refetchBoard();

View File

@@ -16,6 +16,7 @@ export const boardRouter = createTRPCRouter({
if (!userId) return; if (!userId) return;
return ctx.db.query.boards.findMany({ return ctx.db.query.boards.findMany({
where: eq(boards.createdBy, userId),
columns: { columns: {
publicId: true, publicId: true,
name: true, name: true,

View File

@@ -58,10 +58,11 @@ export const cardRouter = createTRPCRouter({
where: eq(cards.publicId, input.id), where: eq(cards.publicId, input.id),
}) })
), ),
updateDescription: publicProcedure update: publicProcedure
.input( .input(
z.object({ z.object({
cardId: z.string(), cardId: z.string().min(12),
title: z.string().min(1),
description: z.string(), description: z.string(),
})) }))
.mutation(({ ctx, input }) => { .mutation(({ ctx, input }) => {
@@ -69,9 +70,9 @@ export const cardRouter = createTRPCRouter({
if (!userId) return; if (!userId) return;
return ctx.db.update(cards).set({ description: input.description}).where(eq(cards.publicId, input.cardId)); return ctx.db.update(cards).set({ title: input.title, description: input.description }).where(eq(cards.publicId, input.cardId));
}), }),
update: publicProcedure reorder: publicProcedure
.input( .input(
z.object({ z.object({
cardId: z.string().min(12), cardId: z.string().min(12),