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",
"react": "18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-contenteditable": "^3.3.7",
"react-dom": "18.2.0",
"react-icons": "^4.11.0",
"react-lottie-player": "^1.5.5",

View File

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

View File

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

View File

@@ -1,84 +1,75 @@
"use client";
import { useParams } from "next/navigation";
import { HiOutlinePlusSmall } from "react-icons/hi2";
import { Formik, Form, Field, type FieldProps } from "formik";
import { useFormik } from "formik";
import ContentEditable from "react-contenteditable";
import { api } from "~/trpc/react";
interface FormValues {
cardId: string;
title: string;
description: string;
}
export default function CardPage() {
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 <></>;
const { data } = api.card.byId.useQuery({ id: cardId });
const updateCard = api.card.updateDescription.useMutation();
return (
<div>
<div className="mb-8 flex w-full justify-between">
<h1 className="font-medium tracking-tight text-dark-1000 sm:text-[1.2rem]">
{data?.title}
</h1>
<div>
<button
type="button"
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"
>
<HiOutlinePlusSmall
className="-mr-0.5 h-5 w-5"
aria-hidden="true"
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
<div className="mt-2">
<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-1.5 font-medium tracking-tight text-dark-1000 focus:ring-0 sm:text-[1.2rem] sm:leading-6"
/>
New
</button>
</div>
</div>
</form>
</div>
<div className="mb-8 flex w-full max-w-2xl justify-between">
<Formik
initialValues={{
cardId,
description: data?.description ? data.description : "",
}}
onSubmit={(values: FormValues) => {
updateCard.mutate({
cardId: values.cardId,
description: values.description,
});
}}
enableReinitialize
>
<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>
<form onSubmit={formik.handleSubmit} className="w-full space-y-6">
<div className="mt-2">
<ContentEditable
html={formik.values.description || "Add description..."}
disabled={false}
onChange={(e) =>
formik.setFieldValue("description", e.target.value)
}
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"
/>
</div>
</form>
</div>
</div>
);

View File

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

View File

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

View File

@@ -58,10 +58,11 @@ export const cardRouter = createTRPCRouter({
where: eq(cards.publicId, input.id),
})
),
updateDescription: publicProcedure
update: publicProcedure
.input(
z.object({
cardId: z.string(),
cardId: z.string().min(12),
title: z.string().min(1),
description: z.string(),
}))
.mutation(({ ctx, input }) => {
@@ -69,9 +70,9 @@ export const cardRouter = createTRPCRouter({
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(
z.object({
cardId: z.string().min(12),