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:
parent
364d3a1917
commit
1e632c52be
|
@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
))}
|
))}
|
||||||
|
|
Loading…
Reference in New Issue