twitter-clone/app/routes/home.tsx

137 lines
3.7 KiB
TypeScript

import type { PostWithRelations } from "~/utils/prisma.server";
import type {
ActionFunction,
ActionFunctionArgs,
LoaderFunction,
LoaderFunctionArgs,
} from "@remix-run/node";
import { json, redirect } from "@remix-run/node";
import {
Form,
useActionData,
useLoaderData,
useRouteLoaderData,
} from "@remix-run/react";
import { Button } from "~/components/Button";
import { Card } from "~/components/Card";
import { FormLabel, TextArea } from "~/components/Form";
import { Post } from "~/components/Post";
import { SubTitle, Text, Title } from "~/components/Typography";
import { likePost, unLikePost } from "~/models/like.server";
import { createPost, getAllPosts, getFeed } from "~/models/post.server";
import { commitSession, getSession } from "~/utils/session.server";
import type { RootLoaderTypes } from "~/root";
export async function action({ request }: ActionFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
if (!session.has("userId")) {
return redirect("/");
}
const userId = session.get("userId");
const formData = await request
.formData()
.then((data) => Object.fromEntries(data));
switch (formData.intent) {
case "newpost":
const postErrors = await createPost(String(formData.post), userId);
if (Object.values(postErrors).some(Boolean)) {
return postErrors;
}
session.flash("globalMessage", "Post created!");
break;
case "like":
const likeErrors = await likePost(Number(formData.postId), userId);
if (Object.values(likeErrors).some(Boolean)) {
return likeErrors;
}
session.flash("globalMessage", "Post liked!");
break;
case "unlike":
const unLikeErrors = await unLikePost(Number(formData.postId), userId);
if (Object.values(unLikeErrors).some(Boolean)) {
return unLikeErrors;
}
session.flash("globalMessage", "Post unliked!");
break;
default:
return;
}
return json(
{},
{
headers: {
"Set-Cookie": await commitSession(session),
},
}
);
}
export async function loader({ request }: LoaderFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
if (!session.has("userId")) {
return redirect("/");
}
return await getFeed(session.get("userId"));
}
export default function Index() {
const rootData = useRouteLoaderData<RootLoaderTypes>("root");
const data: PostWithRelations[] = useLoaderData<LoaderFunction>();
const errors = useActionData<ActionFunction>();
console.log(data);
return (
<div className="flex flex-col gap-5">
<Title>Home</Title>
<Card>
{rootData?.id ? (
<>
<Title>New post</Title>
<Form className="flex flex-col gap-3" method="POST">
<input type="hidden" name="intent" value={"newpost"} />
<FormLabel>
<Text>Post body</Text>
<TextArea name="post" />
<Text type="error">{errors?.body ? errors.body : ""}</Text>
</FormLabel>
<Button type="submit">Post</Button>
</Form>
</>
) : (
<>
<Title>Twitter clone</Title>
<SubTitle>Made with Remix</SubTitle>
</>
)}
</Card>
<SubTitle>Feed</SubTitle>
{data.length > 0 ? (
<Card className="!p-0 !gap-0 divide-y">
{data.map((post: PostWithRelations) => (
<Post userId={rootData?.id} key={post.id} post={post} />
))}
</Card>
) : (
<Text type="error">
Feed is empty, follow someone so their recent posts will show up here!
</Text>
)}
</div>
);
}