feat: add card page

This commit is contained in:
Henry
2023-11-27 23:27:44 +00:00
parent 3d4df5f7e5
commit 1860db7a9c
10 changed files with 728 additions and 110 deletions

View File

@@ -0,0 +1,65 @@
import Image from "next/image";
import { redirect } from "next/navigation";
import { getServerAuthSession } from "~/server/auth";
import boardsIcon from "~/app/assets/boards.json";
import ReactiveButton from "~/app/components/ReactiveButton";
const navigation = [
{ name: "Boards", href: "/boards", icon: boardsIcon, current: true },
];
export default async function Layout(props: { children: React.ReactNode }) {
const session = await getServerAuthSession();
if (!session?.user) redirect("api/auth/signin");
return (
<main className="flex h-screen flex-col items-center bg-dark-50">
<div className="m-auto flex h-16 w-full justify-between border-b border-dark-600 px-5 py-2 align-middle">
<div className="my-auto flex">
<h1 className="text-lg font-normal tracking-tight text-dark-1000">
kan
</h1>
</div>
</div>
<div className="flex h-full w-full">
<nav className="flex w-72 flex-col justify-between border-r border-dark-600 px-5 py-5">
<div>
<ul role="list" className="-mx-2 my-6 space-y-1">
{navigation.map((item) => (
<li key={item.name}>
<ReactiveButton
href={item.href}
current={item.current}
name={item.name}
json={item.icon}
/>
</li>
))}
</ul>
</div>
<button className="flex items-center">
{session?.user.image ? (
<Image
src={session?.user.image ?? ""}
className="h-8 w-8 rounded-full bg-gray-50"
width={30}
height={30}
alt=""
/>
) : null}
<p className="ml-2 truncate text-sm text-dark-1000">
{session?.user.email}
</p>
</button>
</nav>
<div className="w-full p-8">{props.children}</div>
</div>
</main>
);
}

View File

@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { HiOutlinePlusSmall } from "react-icons/hi2";
import {
@@ -180,17 +180,16 @@ export default function BoardPage() {
index={index}
>
{(provided) => (
<div
<Link
key={card.publicId}
className="mb-2 rounded-md border border-dark-200 bg-dark-500 px-3 py-2"
href={`/cards/${card.publicId}`}
className="mb-2 flex !cursor-pointer rounded-md border border-dark-200 bg-dark-500 px-3 py-2 text-sm text-dark-1000"
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<p className="text-sm text-dark-1000">
{card.title}
</p>
</div>
{card.title}
</Link>
)}
</Draggable>
))}

View File

@@ -1,65 +1,5 @@
import Image from "next/image";
import { redirect } from "next/navigation";
import Dashboard from "~/app/_components/dashboard";
import { getServerAuthSession } from "~/server/auth";
import boardsIcon from "~/app/assets/boards.json";
import ReactiveButton from "~/app/components/ReactiveButton";
const navigation = [
{ name: "Boards", href: "/boards", icon: boardsIcon, current: true },
];
export default async function Layout(props: { children: React.ReactNode }) {
const session = await getServerAuthSession();
if (!session?.user) redirect("api/auth/signin");
return (
<main className="flex h-screen flex-col items-center bg-dark-50">
<div className="m-auto flex h-16 w-full justify-between border-b border-dark-600 px-5 py-2 align-middle">
<div className="my-auto flex">
<h1 className="text-lg font-normal tracking-tight text-dark-1000">
kan
</h1>
</div>
</div>
<div className="flex h-full w-full">
<nav className="flex w-72 flex-col justify-between border-r border-dark-600 px-5 py-5">
<div>
<ul role="list" className="-mx-2 my-6 space-y-1">
{navigation.map((item) => (
<li key={item.name}>
<ReactiveButton
href={item.href}
current={item.current}
name={item.name}
json={item.icon}
/>
</li>
))}
</ul>
</div>
<button className="flex items-center">
{session?.user.image ? (
<Image
src={session?.user.image ?? ""}
className="h-8 w-8 rounded-full bg-gray-50"
width={30}
height={30}
alt=""
/>
) : null}
<p className="ml-2 truncate text-sm text-dark-1000">
{session?.user.email}
</p>
</button>
</nav>
<div className="w-full p-8">{props.children}</div>
</div>
</main>
);
export default function Layout(props: { children: React.ReactNode }) {
return <Dashboard>{props.children}</Dashboard>;
}

View File

@@ -0,0 +1,85 @@
"use client";
import { useParams } from "next/navigation";
import { HiOutlinePlusSmall } from "react-icons/hi2";
import { Formik, Form, Field, type FieldProps } from "formik";
import { api } from "~/trpc/react";
interface FormValues {
cardId: string;
description: string;
}
export default function CardPage() {
const params = useParams();
const cardId = params?.id?.length && params.id[0];
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"
/>
New
</button>
</div>
</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>
</div>
</div>
);
}

5
src/app/cards/layout.tsx Normal file
View File

@@ -0,0 +1,5 @@
import Dashboard from "~/app/_components/dashboard";
export default function Layout(props: { children: React.ReactNode }) {
return <Dashboard>{props.children}</Dashboard>;
}