diff --git a/prisma/migrations/20250825191729_add_estimated_time_column/migration.sql b/prisma/migrations/20250825191729_add_estimated_time_column/migration.sql new file mode 100644 index 0000000..92a768f --- /dev/null +++ b/prisma/migrations/20250825191729_add_estimated_time_column/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Post" ADD COLUMN "estimated_time" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/migrations/20250826002145_add_views_to_post/migration.sql b/prisma/migrations/20250826002145_add_views_to_post/migration.sql new file mode 100644 index 0000000..505c012 --- /dev/null +++ b/prisma/migrations/20250826002145_add_views_to_post/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Post" ADD COLUMN "views" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/migrations/20250826015513_remove_views_column/migration.sql b/prisma/migrations/20250826015513_remove_views_column/migration.sql new file mode 100644 index 0000000..af87405 --- /dev/null +++ b/prisma/migrations/20250826015513_remove_views_column/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `views` on the `Post` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Post" DROP COLUMN "views"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9b2bdfc..c049da5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -43,6 +43,7 @@ model Post { coverImageLink String? slug String @unique previewImageLink String? + estimated_time Int @default(0) authorId Int categoryId Int createdAt DateTime @default(now()) diff --git a/src/modules/posts/posts.controller.ts b/src/modules/posts/posts.controller.ts index 33cf5f4..0bbdb58 100644 --- a/src/modules/posts/posts.controller.ts +++ b/src/modules/posts/posts.controller.ts @@ -1,38 +1,43 @@ -import { Controller, Get, Param } from '@nestjs/common'; +import { + Body, + Controller, + Delete, + Get, + Param, + Patch, + Post, +} from '@nestjs/common'; import { PostsService } from './posts.service'; import { Post as PostModel } from '@prisma/client'; +import { CreatePostDto } from './dto/create-post.dto'; +import { UpdatePostDto } from './dto/update-post.dto'; @Controller('posts') export class PostsController { constructor(private readonly postService: PostsService) {} - @Get('published') - async findPublishedPosts(): Promise { - return this.postService.posts({ - where: { isPublished: true }, - }); + @Post() + async create(@Body() dto: CreatePostDto) { + return this.postService.createPost(dto); } - @Get('filtered-posts/:searchString') - async findFilteredPosts( - @Param('searchString') searchString: string, - ): Promise { - return this.postService.posts({ - where: { - OR: [ - { - title: { contains: searchString }, - }, - { - content: { contains: searchString }, - }, - ], - }, - }); + @Get('published') + async findPublishedPosts(): Promise { + return this.postService.findPublishedPosts(); } @Get(':slug') async findPostBySlug(@Param('slug') slug: string): Promise { return this.postService.findPostBySlug(slug); } + + @Patch(':slug') + update(@Param('slug') slug: string, @Body() dto: UpdatePostDto) { + return this.postService.updatePost(slug, dto); + } + + @Delete(':slug') + remove(@Param('slug') slug: string) { + return this.postService.removePost(slug); + } } diff --git a/src/modules/posts/posts.service.ts b/src/modules/posts/posts.service.ts index 02f1c06..2f68add 100644 --- a/src/modules/posts/posts.service.ts +++ b/src/modules/posts/posts.service.ts @@ -1,11 +1,43 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../../prisma.service'; -import { Post, Prisma } from '@prisma/client'; +import { Post } from '@prisma/client'; +import { CreatePostDto } from './dto/create-post.dto'; +import { UpdatePostDto } from './dto/update-post.dto'; @Injectable() export class PostsService { constructor(private prisma: PrismaService) {} + private calculateEstimatedTime(content: string): number { + if (!content) { + new NotFoundException('Conteúdo não encontrado!'); + return 0; + } + + const countWords = content.trim().split(/\s+/).length; + + return Math.ceil(countWords / 200); + } + + async createPost(data: CreatePostDto): Promise { + const estimated_time = this.calculateEstimatedTime(data.content as string); + + return this.prisma.post.create({ + data: { + title: data.title, + previewContent: data.previewContent, + content: data.content, + slug: data.slug, + isPublished: data.isPublished, + coverImageLink: data.coverImageLink, + previewImageLink: data.previewImageLink, + estimated_time, + author: { connect: { id: data.authorId } }, + category: { connect: { id: data.categoryId } }, + }, + }); + } + async findPostBySlug(slug: string): Promise { const post = await this.prisma.post.findUnique({ where: { slug }, @@ -24,26 +56,17 @@ export class PostsService { }); if (!post) { - throw new NotFoundException('Post not found!'); + throw new NotFoundException('Artigo não encontrado!'); } return post; } - async posts(params: { - skip?: number; - take?: number; - cursor?: Prisma.PostWhereUniqueInput; - where?: Prisma.PostWhereInput; - orderBy?: Prisma.PostOrderByWithRelationInput; - }): Promise { - const { skip, take, cursor, where, orderBy } = params; - return this.prisma.post.findMany({ - skip, - take, - cursor, - where, - orderBy, + async findPublishedPosts(): Promise { + const posts = await this.prisma.post.findMany({ + where: { + isPublished: true, + }, include: { category: { select: { @@ -57,28 +80,37 @@ export class PostsService { }, }, }); - } - async createPost(data: Prisma.PostCreateInput): Promise { - return this.prisma.post.create({ - data, - }); + if (!posts) { + throw new NotFoundException('Artigos não encontrados!'); + } + + return posts; } - async updatePost(params: { - where: Prisma.PostWhereUniqueInput; - data: Prisma.PostUpdateInput; - }): Promise { - const { data, where } = params; - return this.prisma.post.update({ - data, - where, - }); + async updatePost(slug: string, data: UpdatePostDto) { + const findPost = await this.findPostBySlug(slug); + + if (!findPost) { + throw new NotFoundException( + `Não foi encontrado o artigo com o slug "${slug}"`, + ); + } + + return this.prisma.post.update({ where: { slug }, data }); } - async deletePost(where: Prisma.PostWhereUniqueInput): Promise { - return this.prisma.post.delete({ - where, - }); + async removePost(slug: string) { + const findPost = await this.findPostBySlug(slug); + + if (!findPost) { + throw new NotFoundException( + `Não foi encontrado o artigo com o slug "${slug}"`, + ); + } + + await this.prisma.post.delete({ where: { slug } }); + + return { message: 'Artigo removido com sucesso!' }; } }