Skip to content

Commit

Permalink
Merge pull request #7 from kir-dev/comment_crud
Browse files Browse the repository at this point in the history
Comment CRUD
  • Loading branch information
justnyx authored Nov 20, 2024
2 parents 6ffdcd3 + b00d787 commit 7e3c60d
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 5 deletions.
2 changes: 2 additions & 0 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"@nestjs/platform-express": "^10.3.8",
"@nestjs/swagger": "^7.3.1",
"@prisma/client": "^5.13.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"nestjs-prisma": "^0.23.0",
"reflect-metadata": "^0.2.2",
"rimraf": "^5.0.5",
Expand Down
35 changes: 35 additions & 0 deletions apps/backend/src/comments/comments.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, Query } from '@nestjs/common';

import { CommentsService } from './comments.service';
import { CreateCommentDto } from './dto/create-comment.dto';
import { UpdateCommentDto } from './dto/update-comment.dto';

@Controller('comments')
export class CommentsController {
constructor(private readonly commentsService: CommentsService) {}

@Post()
create(@Body() createCommentDto: CreateCommentDto) {
return this.commentsService.create(createCommentDto);
}

@Get()
findAll(@Query('page', ParseIntPipe) page: number, @Query('page_size', ParseIntPipe) pageSize: number) {
return this.commentsService.findAll(page, pageSize);
}

@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.commentsService.findOne(id);
}

@Patch(':id')
update(@Param('id', ParseIntPipe) id: number, @Body() updateCommentDto: UpdateCommentDto) {
return this.commentsService.update(id, updateCommentDto);
}

@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number) {
return this.commentsService.remove(id);
}
}
10 changes: 10 additions & 0 deletions apps/backend/src/comments/comments.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';

import { CommentsController } from './comments.controller';
import { CommentsService } from './comments.service';

@Module({
controllers: [CommentsController],
providers: [CommentsService],
})
export class CommentsModule {}
102 changes: 102 additions & 0 deletions apps/backend/src/comments/comments.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from 'nestjs-prisma';

import { PaginationDto } from '../dto/pagination.dto';
import { CreateCommentDto } from './dto/create-comment.dto';
import { UpdateCommentDto } from './dto/update-comment.dto';
import { Comment } from './entities/comment.entity';

@Injectable()
export class CommentsService {
constructor(private readonly prisma: PrismaService) {}

create(createCommentDto: CreateCommentDto) {
return this.prisma.comment.create({
data: {
...createCommentDto,
},
});
}

findAll(page?: number, pageSize?: number): Promise<PaginationDto<Comment>> {
const hasPagination = page !== -1 && pageSize !== -1;
const comments = this.prisma.comment.findMany({
skip: hasPagination ? (page - 1) * pageSize : undefined,
take: hasPagination ? pageSize : undefined,
orderBy: {
startTime: 'asc',
},
});

const count = this.prisma.reservation.count();

return Promise.all([comments, count])
.then(([comments, count]) => {
const limit = hasPagination ? Math.floor(count / pageSize) : 0;
return {
data: comments,
count,
page,
limit,
};
})
.catch(() => {
throw new InternalServerErrorException('An error occurred.');
});
}

async findOne(id: number) {
try {
return await this.prisma.comment.findUniqueOrThrow({
where: {
id,
},
});
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2025') {
throw new NotFoundException(`This comment doesn't exist.`);
}
throw new InternalServerErrorException('An error occurred.');
}
}
}

async update(id: number, updateCommentDto: UpdateCommentDto) {
try {
return await this.prisma.comment.update({
where: {
id,
},
data: {
...updateCommentDto,
},
});
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2025') {
throw new NotFoundException(`This comment doesn't exist.`);
}
throw new InternalServerErrorException('An error occurred.');
}
}
}

async remove(id: number) {
try {
return await this.prisma.comment.delete({
where: {
id,
},
});
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
if (e.code === 'P2025') {
throw new NotFoundException(`This comment doesn't exist.`);
}
throw new InternalServerErrorException('An error occurred.');
}
}
}
}
5 changes: 5 additions & 0 deletions apps/backend/src/comments/dto/create-comment.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { OmitType } from '@nestjs/swagger';

import { Comment } from '../entities/comment.entity';

export class CreateCommentDto extends OmitType(Comment, ['id']) {}
5 changes: 5 additions & 0 deletions apps/backend/src/comments/dto/update-comment.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PartialType } from '@nestjs/mapped-types';

import { CreateCommentDto } from './create-comment.dto';

export class UpdateCommentDto extends PartialType(CreateCommentDto) {}
16 changes: 16 additions & 0 deletions apps/backend/src/comments/entities/comment.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IsDate, IsNumber, IsPositive, IsString } from 'class-validator';

export class Comment {
@IsNumber()
@IsPositive()
id: number;

@IsString()
comment: string;

@IsDate()
startTime: Date;

@IsDate()
endTime: Date;
}
6 changes: 6 additions & 0 deletions apps/backend/src/dto/pagination.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type PaginationDto<T> = {
data: T[];
count: number;
page: number;
limit: number;
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"dependencies": {
"@nestjs/mapped-types": "*"
},
"name": "next-nest-template",
"version": "0.0.0",
"description": "Template repository for full-stack NestJS + NextJS projects",
Expand Down
81 changes: 76 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@
path-to-regexp "3.2.0"
tslib "2.6.2"

"@nestjs/mapped-types@*":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz#d2d8523709fd5d872a9b9e0c38162746e2a7f44e"
integrity sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==

"@nestjs/[email protected]":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@nestjs/mapped-types/-/mapped-types-2.0.5.tgz#485d6b44e19779c98d04e52bd1d2bcc7001df0ea"
Expand Down Expand Up @@ -648,6 +653,11 @@
"@types/node" "*"
"@types/send" "*"

"@types/validator@^13.11.8":
version "13.12.2"
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.12.2.tgz#760329e756e18a4aab82fc502b51ebdfebbe49f5"
integrity sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==

"@typescript-eslint/eslint-plugin@^7.7.1":
version "7.7.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz#50a9044e3e5fe76b22caf64fb7fc1f97614bdbfd"
Expand Down Expand Up @@ -1027,6 +1037,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"

ansi-styles@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==

any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
Expand Down Expand Up @@ -1377,6 +1392,20 @@ chrome-trace-event@^1.0.2:
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==

class-transformer@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336"
integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==

class-validator@^0.14.1:
version "0.14.1"
resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.14.1.tgz#ff2411ed8134e9d76acfeb14872884448be98110"
integrity sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==
dependencies:
"@types/validator" "^13.11.8"
libphonenumber-js "^1.10.53"
validator "^13.9.0"

class-variance-authority@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522"
Expand Down Expand Up @@ -1708,6 +1737,11 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"

eastasianwidth@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==

[email protected]:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
Expand Down Expand Up @@ -3053,6 +3087,11 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"

libphonenumber-js@^1.10.53:
version "1.11.14"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.11.14.tgz#d753524fd30e6433834a1464baf7efed4a06b593"
integrity sha512-sexvAfwcW1Lqws4zFp8heAtAEXbEDnvkYCEGzvOoMgZR7JhXo/IkE9MkkGACgBed5fWqh3ShBGnJBdDnU9N8EQ==

lilconfig@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
Expand Down Expand Up @@ -4193,7 +4232,7 @@ streamsearch@^1.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@4.1.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.1.2:
string-width@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff"
integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==
Expand All @@ -4202,6 +4241,24 @@ [email protected], string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.
is-fullwidth-code-point "^3.0.0"
strip-ansi "^5.2.0"

string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
dependencies:
eastasianwidth "^0.2.0"
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"

string.prototype.matchall@^4.0.10:
version "4.0.11"
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a"
Expand Down Expand Up @@ -4707,6 +4764,11 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==

validator@^13.9.0:
version "13.12.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f"
integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==

vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
Expand Down Expand Up @@ -4846,15 +4908,24 @@ which@^2.0.1:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@7.0.0, wrap-ansi@^6.0.1, wrap-ansi@^6.2.0, wrap-ansi@^8.1.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
dependencies:
ansi-styles "^6.1.0"
string-width "^5.0.1"
strip-ansi "^7.0.1"

wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
Expand Down

0 comments on commit 7e3c60d

Please sign in to comment.