A lot of code trying to make the replies work (I can't recursively show all parent replies because Prisma hasn't implemented recursive relation includes after 2 years of the initial request, which sucks)

This commit is contained in:
Joonas 2023-11-18 17:53:07 +02:00
parent 364d3a1917
commit 1e632c52be
3 changed files with 332 additions and 120 deletions

View File

@ -3,9 +3,8 @@ import { Button } from "./Button";
import { Card } from "./Card"; import { Card } from "./Card";
import { FormLabel, TextArea } from "./Form"; import { FormLabel, TextArea } from "./Form";
import { SubTitle, Text } from "./Typography"; import { SubTitle, Text } from "./Typography";
import type { User } from "@prisma/client";
import type { PostWithRelations } from "~/utils/prisma.server"; import type { PostWithRelations } from "~/utils/prisma.server";
import { ReactNode } from "react"; import type { ReactNode } from "react";
export function Poster({ export function Poster({
username, username,
@ -72,11 +71,17 @@ export function Post({
userId, userId,
post, post,
topTitle, topTitle,
child,
reply,
enlarge,
rootPostId, rootPostId,
}: { }: {
post: PostWithRelations; post: PostWithRelations;
userId?: number; userId?: number;
topTitle?: ReactNode; topTitle?: ReactNode;
child?: boolean;
reply?: boolean;
enlarge?: boolean;
rootPostId?: number; rootPostId?: number;
}) { }) {
const fetcher = useFetcher(); const fetcher = useFetcher();
@ -86,16 +91,64 @@ export function Post({
return ( return (
<> <>
{post?.parentReply ? ( {post?.parentReply?.text ? (
<Post post={post.parentReply} userId={userId} rootPostId={rootPostId} /> <>
<Post
post={post.parentReply}
userId={userId}
child={true}
reply={true}
rootPostId={rootPostId}
topTitle={
<>
Replying to{" "}
{post.parentReply.parentReply ? (
<Poster
style="compact"
username={post.parentReply.parentReply.author.username}
name={post.parentReply.parentReply.author.name}
pfp={post.parentReply.parentReply.author.pfp}
/>
) : (
<Poster
style="compact"
username={post.parentReply.post.author.username}
name={post.parentReply.post.author.name}
pfp={post.parentReply.post.author.pfp}
/>
)}
</>
}
/>
<div className="h-8 pl-[39px]">
<div className="border w-0 h-full"></div>
</div>
</>
) : ( ) : (
"" ""
)} )}
<div <div
key={post.id} key={post.id}
className="flex relative flex-col gap-4 p-6 transition-all bg-ctp-mantle/20 hover:bg-ctp-base first:rounded-t-lg last:rounded-b-lg " className={`flex relative flex-col ${
enlarge ? "text-xl" : ""
} gap-4 transition-all bg-ctp-mantle/20 hover:bg-ctp-base first:rounded-t-lg last:rounded-b-lg`}
> >
{topTitle ? <Text type="subtitle">{topTitle}</Text> : ""} <div
className={` ${!child && reply ? `border-y py-4` : ""} ${
!reply ? "!p-4" : ""
} px-4`}
>
<div className="flex gap-4">
<div className="flex flex-col justify-center items-center min-h-full">
<img
className="w-12 h-12 rounded-full"
src={`/uploads/${post.author.pfp}`}
alt=""
/>
{child ? <div className="w-0 border h-full"></div> : ""}
</div>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2">
{post.reposters?.length > 0 ? ( {post.reposters?.length > 0 ? (
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
{post.reposters.map((user) => ( {post.reposters.map((user) => (
@ -112,12 +165,29 @@ export function Post({
) : ( ) : (
"" ""
)} )}
<div className="flex items-center"> {topTitle ? (
<Poster <Text className="flex gap-1" type="subtitle">
pfp={post.author.pfp} {topTitle}
username={post.author.username} </Text>
name={post.author.name} ) : (
/> ""
)}
<div className="flex gap-2">
{post.author.name ? (
<>
<SubTitle>{post.author.name}</SubTitle>
<Link to={`/users/${post.author.username}`}>
<Text type="link">@{post.author.username}</Text>
</Link>
</>
) : (
<SubTitle>
<Link to={`/users/${post.author.username}`}>
<Text type="link">@{post.author.username}</Text>
</Link>
</SubTitle>
)}
</div>
</div> </div>
<Link to={`/${rootPostId ? "reply" : "post"}/${post.id}`}> <Link to={`/${rootPostId ? "reply" : "post"}/${post.id}`}>
<div> <div>
@ -169,7 +239,11 @@ export function Post({
<input type="hidden" name="intent" value={"reply"} /> <input type="hidden" name="intent" value={"reply"} />
{rootPostId ? ( {rootPostId ? (
<> <>
<input type="hidden" name="postId" value={rootPostId} /> <input
type="hidden"
name="postId"
value={rootPostId}
/>
<input type="hidden" name="replyId" value={post.id} /> <input type="hidden" name="replyId" value={post.id} />
</> </>
) : ( ) : (
@ -185,6 +259,9 @@ export function Post({
</details> </details>
</div> </div>
</div> </div>
</div>
</div>
</div>
</> </>
); );
} }

View File

@ -14,7 +14,7 @@ import { Card } from "~/components/Card";
import { SubTitle, Text, Title } from "~/components/Typography"; import { SubTitle, Text, Title } from "~/components/Typography";
import type { PostWithRelations } from "~/utils/prisma.server"; import type { PostWithRelations } from "~/utils/prisma.server";
import { prisma } from "~/utils/prisma.server"; import { prisma } from "~/utils/prisma.server";
import { Post } from "~/components/Post"; import { Post, Poster } from "~/components/Post";
import type { RootLoaderTypes } from "~/root"; import type { RootLoaderTypes } from "~/root";
import { Button } from "~/components/Button"; import { Button } from "~/components/Button";
import { FormLabel, TextArea } from "~/components/Form"; import { FormLabel, TextArea } from "~/components/Form";
@ -166,9 +166,14 @@ export default function PostRoute() {
return ( return (
<div className="flex flex-col gap-5"> <div className="flex flex-col gap-5">
<Title>Post</Title> <Title>Post</Title>
<Card className="!p-0 !gap-0 divide-y"> <Card className="!p-0 !gap-0">
<div className="bg-ctp-pink/5"> <div className="border-b">
<Post key={data.id} post={data} userId={rootData?.id} /> <Post
key={data.id}
post={data}
enlarge={true}
userId={rootData?.id}
/>
</div> </div>
{rootData?.id ? ( {rootData?.id ? (
<div className="p-6 !bg-ctp-sky/5"> <div className="p-6 !bg-ctp-sky/5">
@ -192,7 +197,23 @@ export default function PostRoute() {
)} )}
{data.replies.map((reply) => ( {data.replies.map((reply) => (
<div key={reply.id}> <div key={reply.id}>
<Post post={reply} userId={rootData?.id} rootPostId={data.id} /> <Post
post={reply}
userId={rootData?.id}
rootPostId={data.id}
reply={true}
topTitle={
<Text className="flex gap-1" type="subtitle">
Replying to{" "}
<Poster
style="compact"
username={data.author.username}
name={data.author.name}
pfp={data.author.pfp}
/>
</Text>
}
/>
</div> </div>
))} ))}
</Card> </Card>

View File

@ -14,7 +14,7 @@ import { Card } from "~/components/Card";
import { SubTitle, Text, Title } from "~/components/Typography"; import { SubTitle, Text, Title } from "~/components/Typography";
import type { PostWithRelations } from "~/utils/prisma.server"; import type { PostWithRelations } from "~/utils/prisma.server";
import { prisma } from "~/utils/prisma.server"; import { prisma } from "~/utils/prisma.server";
import { Post } from "~/components/Post"; import { Post, Poster } from "~/components/Post";
import type { RootLoaderTypes } from "~/root"; import type { RootLoaderTypes } from "~/root";
import { Button } from "~/components/Button"; import { Button } from "~/components/Button";
import { FormLabel, TextArea } from "~/components/Form"; import { FormLabel, TextArea } from "~/components/Form";
@ -53,26 +53,6 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
id: true, id: true,
text: true, text: true,
createdAt: true, createdAt: true,
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
likes: {
select: {
id: true,
userId: true,
},
},
reposts: {
select: {
id: true,
userId: true,
},
},
parentReply: { parentReply: {
select: { select: {
id: true, id: true,
@ -86,6 +66,42 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
pfp: true, pfp: true,
}, },
}, },
post: {
include: {
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
},
},
parentReply: {
select: {
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
post: {
include: {
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
},
},
},
},
likes: { likes: {
select: { select: {
id: true, id: true,
@ -105,6 +121,74 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
}, },
}, },
}, },
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
likes: {
select: {
id: true,
userId: true,
},
},
post: {
select: {
id: true,
text: true,
createdAt: true,
likes: {
select: {
id: true,
userId: true,
postId: true,
user: {
select: {
username: true,
name: true,
pfp: true,
},
},
},
},
reposts: {
select: {
id: true,
userId: true,
postId: true,
user: {
select: {
username: true,
name: true,
pfp: true,
},
},
},
},
author: {
select: {
id: true,
username: true,
name: true,
pfp: true,
},
},
_count: {
select: {
replies: true,
},
},
},
},
reposts: {
select: {
id: true,
userId: true,
},
},
_count: { _count: {
select: { select: {
childReplies: true, childReplies: true,
@ -257,20 +341,49 @@ export default function ReplyRoute() {
const rootData = useRouteLoaderData<RootLoaderTypes>("root"); const rootData = useRouteLoaderData<RootLoaderTypes>("root");
const data: PostWithRelations = useLoaderData<LoaderFunction>(); const data: PostWithRelations = useLoaderData<LoaderFunction>();
const errors = useActionData<ActionFunction>(); const errors = useActionData<ActionFunction>();
console.log(data);
return ( return (
<div className="flex flex-col gap-5"> <div className="flex flex-col gap-5">
<Title>Post</Title> <Title>Post</Title>
<Card className="!p-0 !gap-0 divide-y"> <Card className="!p-0 !pt-6 !gap-0">
<div className="text-sm"> <Post
<Post key={data.id} post={data.post} userId={rootData?.id} /> post={data.post}
userId={rootData?.id}
child={true}
reply={true}
/>
<div className="h-8 pl-[39px]">
<div className="border w-0 h-full"></div>
</div> </div>
<div className="text-xl bg-ctp-pink/5"> <div>
<Post <Post
key={data.id} key={data.id}
post={data} post={data}
userId={rootData?.id} userId={rootData?.id}
rootPostId={data.post.id} rootPostId={data.post.id}
enlarge={true}
reply={true}
topTitle={
<>
Replying to
{data.parentReply ? (
<Poster
style="compact"
username={data.parentReply.author.username}
name={data.parentReply.author.name}
pfp={data.parentReply.author.pfp}
/>
) : (
<Poster
style="compact"
username={data.post.author.username}
name={data.post.author.name}
pfp={data.post.author.pfp}
/>
)}
</>
}
/> />
</div> </div>
{rootData?.id ? ( {rootData?.id ? (
@ -300,6 +413,7 @@ export default function ReplyRoute() {
post={reply} post={reply}
userId={rootData?.id} userId={rootData?.id}
rootPostId={data.post.id} rootPostId={data.post.id}
reply={true}
/> />
</div> </div>
))} ))}