like and unlike post
This commit is contained in:
parent
9e5dc4a740
commit
001cce5374
|
|
@ -17,6 +17,7 @@ model User {
|
||||||
password String
|
password String
|
||||||
posts Post[]
|
posts Post[]
|
||||||
role Role @default(USER)
|
role Role @default(USER)
|
||||||
|
likes Like[]
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Role {
|
enum Role {
|
||||||
|
|
@ -32,4 +33,14 @@ model Post {
|
||||||
author User @relation(fields: [authorId], references: [id])
|
author User @relation(fields: [authorId], references: [id])
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
likes Int @default(0)
|
||||||
|
likedBy Like[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model Like {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
userId Int
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
postId Int
|
||||||
|
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import getPosts from './getPosts';
|
||||||
import postPost from './newPost';
|
import postPost from './newPost';
|
||||||
import putPost from './editPost';
|
import putPost from './editPost';
|
||||||
import deletePost from './deletePost';
|
import deletePost from './deletePost';
|
||||||
|
import likePost from './likePost';
|
||||||
|
import unlikePost from './unlikePost';
|
||||||
|
|
||||||
const posts = Router();
|
const posts = Router();
|
||||||
|
|
||||||
|
|
@ -10,5 +12,7 @@ posts.get('/', getPosts);
|
||||||
posts.post('/new', postPost);
|
posts.post('/new', postPost);
|
||||||
posts.put('/edit/:id', putPost);
|
posts.put('/edit/:id', putPost);
|
||||||
posts.delete('/delete/:id', deletePost);
|
posts.delete('/delete/:id', deletePost);
|
||||||
|
posts.put('/like/:id', likePost);
|
||||||
|
posts.put('/unlike/:id', unlikePost);
|
||||||
|
|
||||||
export default posts;
|
export default posts;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { likePost } from '@/controller/PostController';
|
||||||
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const id = parseInt(req.params.id);
|
||||||
|
const userId = 1; // hardcoded for now, use userId from token
|
||||||
|
const likedPost = await likePost(id, userId);
|
||||||
|
if (likedPost instanceof Error) {
|
||||||
|
return res.status(403).send(likedPost.message);
|
||||||
|
}
|
||||||
|
return res.status(200).send({ message: 'Post liked' });
|
||||||
|
} catch (error) {
|
||||||
|
return res.status(500).send(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { unlikePost } from '@/controller/PostController';
|
||||||
|
import { Request, Response } from 'express';
|
||||||
|
|
||||||
|
export default async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
const postId = parseInt(req.params.id);
|
||||||
|
const userId = 1; // hardcoded for now, use userId from token
|
||||||
|
const likedPost = await unlikePost(postId, userId);
|
||||||
|
if (likedPost instanceof Error) {
|
||||||
|
return res.status(403).send(likedPost.message);
|
||||||
|
}
|
||||||
|
return res.status(200).send({ message: 'Post unliked' });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
return res.status(500).send(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PrismaClient, Post as PrismaPost, User } from '@prisma/client';
|
import { PrismaClient, Post as PrismaPost, Like } from '@prisma/client';
|
||||||
import { Post } from '@/models/PostModel';
|
import { Post } from '@/models/PostModel';
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
|
|
@ -15,6 +15,9 @@ const getPostById = async (id: number): Promise<PrismaPost | null> => {
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
|
include: {
|
||||||
|
likedBy: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return post;
|
return post;
|
||||||
};
|
};
|
||||||
|
|
@ -23,6 +26,7 @@ const getAllPosts = async (): Promise<PrismaPost[]> => {
|
||||||
const posts = prisma.post.findMany({
|
const posts = prisma.post.findMany({
|
||||||
include: {
|
include: {
|
||||||
author: true,
|
author: true,
|
||||||
|
likedBy: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return (await posts).map((post) => {
|
return (await posts).map((post) => {
|
||||||
|
|
@ -90,4 +94,100 @@ const deletePost = async (id: number, userId: number): Promise<PrismaPost | Erro
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getAllPosts, createPost, editPost, getPostById, deletePost };
|
const unlikePost = async (postId: number, userId: number): Promise<Like | Error> => {
|
||||||
|
const post = await prisma.post.findUnique({
|
||||||
|
where: {
|
||||||
|
id: postId,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
likedBy: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (post === null) {
|
||||||
|
return new Error('Post not found');
|
||||||
|
}
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
likes: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (user === null) {
|
||||||
|
return new Error('User not found');
|
||||||
|
}
|
||||||
|
const like = post.likedBy.find((likes) => likes.postId === postId && likes.userId === userId);
|
||||||
|
if (like === undefined) {
|
||||||
|
return new Error('Post not liked');
|
||||||
|
}
|
||||||
|
|
||||||
|
await prisma.post.update({
|
||||||
|
where: {
|
||||||
|
id: postId,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
likes: {
|
||||||
|
decrement: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return prisma.like.delete({
|
||||||
|
where: {
|
||||||
|
id: like.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const likePost = async (id: number, userId: number): Promise<PrismaPost | Error> => {
|
||||||
|
const post = await prisma.post.findUnique({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
likedBy: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (post === null) {
|
||||||
|
return new Error('Post not found');
|
||||||
|
}
|
||||||
|
// if (post.authorId === userId) {
|
||||||
|
// return new Error('User cannot like their own post');
|
||||||
|
// }
|
||||||
|
if (post.likedBy.some((like) => like.userId === userId)) {
|
||||||
|
return new Error('Post already liked');
|
||||||
|
}
|
||||||
|
const newLike = await prisma.like.create({
|
||||||
|
data: {
|
||||||
|
post: {
|
||||||
|
connect: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
connect: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return prisma.post.update({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
likedBy: {
|
||||||
|
connect: {
|
||||||
|
id: newLike.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
likes: {
|
||||||
|
increment: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getAllPosts, createPost, editPost, getPostById, deletePost, likePost, unlikePost };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { User } from './UserModel';
|
||||||
|
import { Post } from './PostModel';
|
||||||
|
|
||||||
|
interface Like {
|
||||||
|
id?: number | undefined;
|
||||||
|
userId: number;
|
||||||
|
user: User;
|
||||||
|
postId: number;
|
||||||
|
post: Post;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Like: z.ZodType<Like> = z.object({
|
||||||
|
id: z.number().optional(),
|
||||||
|
userId: z.number(),
|
||||||
|
user: User,
|
||||||
|
postId: z.number(),
|
||||||
|
post: Post,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { Like };
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { Like } from './LikeModel';
|
||||||
|
|
||||||
interface Post {
|
interface Post {
|
||||||
id?: number | undefined;
|
id?: number | undefined;
|
||||||
content?: string | undefined;
|
content?: string | undefined;
|
||||||
image?: string | undefined;
|
image?: string | undefined;
|
||||||
authorId: number;
|
authorId: number;
|
||||||
|
likes?: number | undefined;
|
||||||
|
likedBy?: Like[] | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Post: z.ZodType<Post> = z.object({
|
const Post: z.ZodType<Post> = z.object({
|
||||||
|
|
@ -12,6 +15,8 @@ const Post: z.ZodType<Post> = z.object({
|
||||||
content: z.string().optional(),
|
content: z.string().optional(),
|
||||||
image: z.string().optional(),
|
image: z.string().optional(),
|
||||||
authorId: z.number(),
|
authorId: z.number(),
|
||||||
|
likes: z.number().optional(),
|
||||||
|
likedBy: z.array(Like).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export { Post };
|
export { Post };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { Post } from './PostModel';
|
import { Post } from './PostModel';
|
||||||
|
import { Like } from './LikeModel';
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id?: number | undefined;
|
id?: number | undefined;
|
||||||
|
|
@ -9,6 +10,7 @@ interface User {
|
||||||
lastName: string;
|
lastName: string;
|
||||||
role?: string | undefined;
|
role?: string | undefined;
|
||||||
posts?: Post[] | undefined;
|
posts?: Post[] | undefined;
|
||||||
|
likes?: Like[] | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const User: z.ZodType<User> = z.object({
|
const User: z.ZodType<User> = z.object({
|
||||||
|
|
@ -19,6 +21,7 @@ const User: z.ZodType<User> = z.object({
|
||||||
lastName: z.string(),
|
lastName: z.string(),
|
||||||
role: z.string().optional(),
|
role: z.string().optional(),
|
||||||
posts: z.array(Post).optional(),
|
posts: z.array(Post).optional(),
|
||||||
|
likes: z.array(Like).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export { User };
|
export { User };
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue