Skip to content
Snippets Groups Projects
Commit c37fdc2e authored by Yusuf Akgül's avatar Yusuf Akgül :hatching_chick:
Browse files

Merge branch 'rewrite.Gweets' into 'main'

Rewrite.gweets

See merge request !30
parents 0edda241 aea3b5e1
No related branches found
No related tags found
1 merge request!30Rewrite.gweets
Pipeline #38797 passed
Showing
with 602 additions and 230 deletions
......@@ -6,6 +6,10 @@ NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Database for connecting to Prisma
DATABASE_URL="file:./dev.db"
# Database for connecting to Supabase for media
NEXT_PUBLIC_SUPABASE_URL="YOUR_SUPABASE_URL"
NEXT_PUBLIC_SUPABASE_ANON_KEY="YOUR_SUPABASE_ANON_KEY"
# URLs
TWITCH_AUTH_BASE_URL="https://id.twitch.tv/oauth2"
IGDB_BASE_URL="https://api.igdb.com/v4"
......
import AddGameDropdown from "@/components/add-game-dropdown";
import AddGameToFinishedList from "@/components/add-game-to-finished-list";
import AddGameToPlanList from "@/components/add-game-to-plan-list";
import AddGameToPlayingList from "@/components/add-game-to-playing-list";
import AddGameToFavList from "@/components/addGameToFavList";
import { BackHeader } from "@/components/back-header";
import { AspectRatio } from "@/components/ui/aspect-ratio";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
......@@ -36,6 +34,12 @@ export default async function GameDetail({ params }: { params: { gameid: string
return (
<div className="main-content h-full">
<Card className="w-full h-full overflow-hidden">
<div className="p-3">
<BackHeader>
<h1 className="font-bold">Game</h1>
</BackHeader>
</div>
<div className="h-64 overflow-hidden">
<AspectRatio ratio={889 / 500}>
<Image
......
......@@ -7,7 +7,7 @@ export default async function GamesPage() {
return (
<main className="main-content">
<div className="flex justify-center">
<div className="fixed top-30 z-50">
<div className="fixed top-30 z-40">
<ScrollToTop />
</div>
<InfiniteScrollGames />
......
// import { PostCommentForm } from "@/components/comment-gweets";
export default async function PostDetail({ params }: { params: { postid: string } }) {
const postid = params.postid
return (
<div className="main-content px-3 pb-3">
<div className="lg:col-span-1">
{/* <PostCommentForm postid={postid} /> */}
</div>
<div className="side-content">
<div className="flex-col">
</div>
</div>
</div>
)
}
\ No newline at end of file
import { PostGweets } from "@/components/post-gweets";
import { CreateGweet } from "@/components/create-gweet/components/create-gweet";
import { Gweets } from "@/components/gweets/components/gweets";
export default async function HomePage() {
return (
<div className="main-content px-3 pb-3">
<div className="lg:col-span-1">
<PostGweets />
<CreateGweet />
<Gweets />
</div>
<div className="side-content">
......
export default async function Followers() {
return (
<div>
<h1>Followers Page WIP</h1>
</div>
)
}
\ No newline at end of file
export default async function Following() {
return (
<div>
<h1>Following Page WIP</h1>
</div>
)
}
\ No newline at end of file
export default async function Likes() {
return (
<div>
<h1>Likes Page WIP</h1>
</div>
)
}
\ No newline at end of file
......@@ -18,7 +18,7 @@ export default function Loading() {
</div>
<div className="px-6 md:px-12">
{/* <div className="border-b border-gray-400 dark:border-gray-200" /> */}
{/* tweets */}
{/* gweets */}
</div>
</Card >
<div className="side-content">
......
......@@ -56,7 +56,7 @@ export default async function User({ params }: { params: { userid: string } }) {
</div>
<div className="p-6 md:p-12 ss:flex">
<UserAvatar
user={{ name: user.name || null, image: user.image || null }}
user={{ username: user.username, image: user.image || null }}
className="h-52 w-52 -mt-36"
/>
<div className="ml-6 md:ml-12 space-y-3">
......@@ -67,10 +67,9 @@ export default async function User({ params }: { params: { userid: string } }) {
</div>
<div className="px-6 md:px-12">
{/* <div className="border-b border-gray-400 dark:border-gray-200" /> */}
{/* tweets */}
{/* gweets */}
</div>
</Card >
<div className="side-content">
<Card className="p-6 grid items-start gap-2 bg-secondary">
<h1>Media</h1>
......
import { BackHeader } from "@/components/back-header";
import { GweetDetails } from "@/components/gweets/components/gweet-details";
import { Card } from "@/components/ui/card";
export default async function GweetDetailPage() {
return (
<Card className="w-full h-full p-3 xl:p-6 ">
<BackHeader>
<h1 className="font-bold">Gweet</h1>
</BackHeader>
<GweetDetails />
</Card>
);
};
\ No newline at end of file
import FollowersList from "@/components/following-users";
import { getServerSession } from "next-auth";
export default async function Followers() {
// const session = await getServerSession(authOptions);
// if (!session) {
// return <div>Loading...</div>;
// }
return (
<div>
<h1>Followers Page WIP</h1>
{/* <FollowersList userId={parseFloat(session.user?.id)} /> */}
</div>
)
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ export default async function ContentLayout({
return (
<div className="flex min-h-screen flex-col space-y-6">
<header className="sticky top-0 z-40 border-b bg-background">
<header className="sticky top-0 z-50 border-b bg-background">
<div className="container flex h-16 items-center justify-between py-4">
<MainNav />
<SearchInput className="p-3 md:w-2/3 2xl:w-1/3" />
......
import { db } from "@/lib/db";
import { getCurrentUser } from "@/lib/session";
import { revalidatePath } from "next/cache";
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const user = await getCurrentUser();
if (!user) {
return NextResponse.json({ status: 401, message: 'Unauthorized' });
}
const userId = user.id;
const content = await req.json()
try {
await db.comment.create({
data: {
message: content.gweet,
postId: content.postId,
userId: userId,
}
})
const path = req.nextUrl.searchParams.get('path') || '/';
revalidatePath(path);
return NextResponse.json({ status: 201, message: 'Comment Created' })
} catch (error: any) {
return NextResponse.json({ status: 500, message: error.message })
}
}
export async function GET(req: NextRequest): Promise<NextResponse> {
const pa = req.nextUrl.searchParams;
try {
const p = pa.get('postid')
if (!p) {
return NextResponse.json({ status: 400, message: 'Bad Request' })
}
const message = await db.post.findUnique({
where: {
id: p
},
include: {
user: true,
},
})
const comments = await db.comment.findMany({
where: {
postId: p
},
orderBy: {
createdAt: "desc"
}
})
return NextResponse.json(comments);
} catch (error) {
return NextResponse.json(error, { status: 500 });
}
}
\ No newline at end of file
import { NextResponse } from "next/server";
import { z } from "zod";
import { db } from "@/lib/db";
// get a single gweet
export async function GET(request: Request, { params }: { params: { id: string } }) {
const { id } = params;
const gweetIdSchema = z.string().cuid();
const zod = gweetIdSchema.safeParse(id);
if (!zod.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zod.error.formErrors,
}, { status: 400 },
);
}
try {
const gweet = await db.gweet.findUnique({
where: {
id,
},
include: {
author: true,
likes: {
include: {
user: {
include: {
followers: true,
},
},
},
orderBy: {
createdAt: "desc",
},
},
media: true,
regweets: {
include: {
user: {
include: {
followers: true,
},
},
},
orderBy: {
createdAt: "desc",
},
},
quote: {
include: {
author: true,
media: true,
},
},
allQuotes: {
include: {
likes: true,
regweets: true,
author: true,
quote: {
include: {
author: true,
},
},
},
orderBy: {
createdAt: "desc",
},
},
allComments: true,
},
});
if (!gweet) {
return NextResponse.json(
{
message: "Gweet not found",
}, { status: 404 },
);
}
return NextResponse.json(gweet, { status: 200 });
} catch (error) {
return NextResponse.json(
{
message: "Something went wrong",
error,
}, { status: 500 },
);
}
}
import { NextResponse } from "next/server";
import { z } from "zod";
import { db } from "@/lib/db";
// get likes from user
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const user_id = searchParams.get("user_id") || undefined;
const userIdSchema = z.string().cuid();
const zod = userIdSchema.safeParse(user_id);
if (!zod.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zod.error.formErrors,
}, { status: 400 },
);
}
try {
const gweets = await db.gweet.findMany({
where: {
likes: {
some: {
userId: user_id,
},
},
},
include: {
author: true,
media: true,
likes: true,
regweets: true,
allComments: true,
},
});
return NextResponse.json(gweets, { status: 200 });
} catch (error: any) {
return NextResponse.json(
{
message: "Something went wrong",
error: error.message,
}, { status: error.errorCode || 500 },
);
}
}
// like and dislike
export async function POST(request: Request) {
const { gweet_id, user_id } = await request.json();
const likeSchema = z
.object({
gweet_id: z.string().cuid(),
user_id: z.string().cuid(),
})
.strict();
const zod = likeSchema.safeParse({ gweet_id, user_id });
if (!zod.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zod.error.formErrors,
}, { status: 400 },
);
}
try {
const like = await db.like.findFirst({
where: {
gweetId: gweet_id,
userId: user_id,
},
});
if (like) {
await db.like.delete({
where: {
id: like.id,
},
});
return NextResponse.json({ message: "Gweet unliked" });
} else {
await db.like.create({
data: {
gweetId: gweet_id,
userId: user_id,
},
});
return NextResponse.json({ message: "Gweet liked" });
}
} catch (error: any) {
return NextResponse.json({
message: "Something went wrong",
error: error.message,
});
}
}
\ No newline at end of file
import { NextResponse } from "next/server";
import { z } from "zod";
import { db } from "@/lib/db";
export async function POST(request: Request) {
const { gweet_id, user_id } = await request.json();
const regweetSchema = z
.object({
gweet_id: z.string().cuid(),
user_id: z.string().cuid(),
})
.strict();
const zod = regweetSchema.safeParse({ gweet_id, user_id });
if (!zod.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zod.error.formErrors,
}, { status: 400 },
);
}
try {
const regweet = await db.regweet.findFirst({
where: {
gweetId: gweet_id,
userId: user_id,
},
});
if (regweet) {
await db.regweet.delete({
where: {
id: regweet.id,
},
});
return NextResponse.json({ message: "Deleted gweet regweet" });
} else {
await db.regweet.create({
data: {
gweetId: gweet_id,
userId: user_id,
},
});
return NextResponse.json({ message: "Gweet regweeted" });
}
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
import { NextResponse } from "next/server";
import { z } from "zod";
import { db } from "@/lib/db";
import { utapi } from "uploadthing/server";
// get gweets
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const type = searchParams.get("type") || undefined;
const id = searchParams.get("id") || undefined;
const cursorQuery = searchParams.get("cursor") || undefined;
const take = Number(searchParams.get("limit")) || 20;
const skip = cursorQuery ? 1 : 0;
const cursor = cursorQuery ? { id: cursorQuery } : undefined;
try {
const gweets = await db.gweet.findMany({
skip,
take,
cursor,
where: {
...(type === "comments" && {
replyToGweetId: id,
}),
...(type === "search" && {
text: {
contains: id,
mode: "insensitive",
},
}),
...(type === "user_gweets" && {
authorId: id,
}),
...(type === "user_replies" && {
authorId: id,
NOT: {
replyToGweetId: null,
},
}),
...(type === "user_likes" && {
likes: {
some: {
userId: id,
},
},
}),
},
include: {
author: true,
likes: true,
media: true,
regweets: true,
quote: {
include: {
author: true,
media: true,
},
},
allComments: true,
allQuotes: true,
},
orderBy: {
createdAt: "desc",
},
});
const nextId = gweets.length < take ? undefined : gweets[gweets.length - 1].id;
return NextResponse.json({ gweets, nextId });
} catch (error) {
return NextResponse.error();
}
}
// create gweet
export async function POST(request: Request) {
const { gweet, fileprops } = await request.json();
const gweetSchema = z
.object({
content: z.string().min(1).max(280),
authorId: z.string().cuid(),
replyToGweetId: z.string().cuid().optional(),
quoteGweetId: z.string().cuid().optional(),
})
.strict();
const zodGweet = gweetSchema.safeParse(gweet);
const mediaSchema = z.array(
z.object({
gweetId: z.string().nullable().optional(),
url: z.string(),
key: z.string(),
type: z.string(),
}).strict()
);
if (!zodGweet.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zodGweet.error.formErrors,
}, { status: 400 },
);
}
try {
const created_gweet = await db.gweet.create({
data: {
...gweet,
},
});
if (fileprops.length > 0) {
const mediaArray = fileprops.map((fileprop: { fileUrl: string; fileKey: string; }) => {
const media = {
gweetId: created_gweet.id,
url: fileprop.fileUrl,
key: fileprop.fileKey,
type: "IMAGE",
}
return media;
});
const zodMedia = mediaSchema.safeParse(mediaArray);
if (!zodMedia.success) {
return NextResponse.json(
{
message: "Invalid media body",
error: zodMedia.error.formErrors,
}, { status: 400 },
);
}
await db.media.createMany({
data: mediaArray,
});
}
return NextResponse.json(created_gweet, { status: 200 });
} catch (error: any) {
console.log(error);
return NextResponse.json(
{
message: "Something went wrong",
error: error.message,
}, { status: error.errorCode || 500 },
);
}
}
// delete gweet
export async function DELETE(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get("id") as string;
const idSchema = z.string().cuid();
const zod = idSchema.safeParse(id);
if (!zod.success) {
return NextResponse.json(
{
message: "Invalid request body",
error: zod.error.formErrors,
}, { status: 400 },
);
}
try {
const checkMedia = await db.media.findMany({
where: {
gweetId: id,
},
});
if (checkMedia.length > 0) {
await utapi.deleteFiles(checkMedia.map((media) => media.key));
}
await db.gweet.delete({
where: {
id,
},
});
return NextResponse.json({ message: "Gweet deleted successfully", });
} catch (error: any) {
return NextResponse.json(
{
message: "Something went wrong",
error: error.message,
}, { status: error.errorCode || 500 },
);
}
}
import { NextResponse } from "next/server";
import { z } from "zod";
import { db } from "@/lib/db";
export async function GET() {
try {
const hashtags = await db.hashtag.findMany({
take: 10,
orderBy: {
score: "desc",
},
});
return NextResponse.json(hashtags, { status: 200 });
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
export async function POST(request: Request) {
const { hashtags } = await request.json();
const hashtagsSchema = z.array(z.string());
const zod = hashtagsSchema.safeParse(hashtags);
if (!zod.success) {
return NextResponse.json({ error: zod.error }, { status: 400 });
}
try {
for (const hashtag of hashtags) {
const hashtagExists = await db.hashtag.findUnique({
where: {
hashtag: hashtag.toLowerCase(),
},
});
if (hashtagExists) {
await db.hashtag.update({
where: {
hashtag: hashtag.toLowerCase(),
},
data: {
score: {
increment: 1,
},
},
});
} else {
await db.hashtag.create({
data: {
text: hashtag,
hashtag: hashtag.toLowerCase(),
},
});
}
}
return NextResponse.json(
{
message: "Hashtag(s) created",
},
{ status: 200 },
);
} catch (error: any) {
return NextResponse.json(
{
error: error.message,
},
{ status: 500 },
);
}
}
import { db } from "@/lib/db"
import { Prisma } from "@prisma/client"
type likeType = Prisma.LikeUncheckedCreateInput
/**
* Creates like if user has not liked this post.
* Deletes like if user has liked post already.
*/
export async function putLike(like: likeType): Promise<likeType | undefined> {
// check if like exists by this user and for this post
// if exists delete
// if not create
try {
const actualLike = await db.like.findFirst({
where: {
// id: like.id,
postId: like.postId,
userId: like.userId
}
})
console.log("found like: ", actualLike?.id)
if (actualLike == null) {
console.log("like is null", "postid:", like.postId, "so create it")
throw Error("Message was not liked by this user")
}
console.log("delete like", like.postId, "likeid: ", actualLike?.id)
await db.like.delete({
where: {
id: actualLike.id
}
})
/* const msg = await db.post.update({
where: {
id: like.postId
},
data: {
likeCount: { increment: -1 }
}
}) */
return undefined;
} catch {
const createdLike = await db.like.create({
data: {
postId: like.postId,
userId: like.userId
}
})
const updatedMessage = await db.post.update({
where: {
id: like.postId
},
data: {
likeCount: { increment: 1 }
}
})
}
}
export async function putLikeComment(like: likeType) {
// check if like exists by this user and for this post
// if exists delete
// if not create
try {
const actualLike = await db.like.findFirst({
where: {
// id: like.id,
postId: like.postId,
commentId: like.commentId,
userId: like.userId
}
})
console.log("found like: ", actualLike?.id)
if (actualLike == null) {
console.log("like is null", like.commentId, "so create it")
const createdLike = await db.like.create({
data: {
postId: like.postId,
userId: like.userId,
commentId: like.commentId
}
})
} else {
console.log("delete like", like.commentId, "postid:", like.postId, "likeid: ", actualLike?.id)
await db.like.delete({
where: {
id: actualLike.id
}
})
}
/* const msg = await db.comment.update({
where: {
id: like.postId
},
data: {
likeCount: { increment: -1 }
}
}) */
} catch {
/* const updatedMessage = await db.comment.update({
where: {
id: like.postId
},
data: {
likeCount: { increment: 1 }
}
}) */
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment