본문 바로가기

프로젝트 개발

23.12.20 (레시피 모델 수정, 리뷰 모델 생성)

 

재료를 배열 안 객체로 수정해 ingredientUnit 삭제

@Column('json')
  ingredient: { item: string; unit: string }[];

 

요리스텝도 배열 안 객체로 생성

@Column('json')
  step: { stepNum: number; des: string; imgUrl: string }[];

 

지금까지 생성한 유저모델과 리뷰 모델과 관계설정

@ManyToMany(() => User, (user) => user.recipes)
  @JoinColumn()
  user: User;

  @ManyToOne(() => Review)
  review: Review;

 

 

dto수정

> 배열 안에 들어가는 객체를 클래스로 만들어 유효성 검사 따로 들어가고 재료랑 스텝에 타입에 클래스로 만든 것 넣기

class IngredientDto {
  @IsString()
  item: string;

  @IsString()
  unit: string;
}

class stepDto {
  @IsNumber()
  stepNum: number;

  @IsString()
  des: string;

  @IsString()
  imgUrl: string;
}
@IsArray()
  @ValidateNested({ each: true })
  @Type(() => IngredientDto)
  ingredient: { item: string; unit: string }[];

  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => stepDto)
  step: { stepNum: number; des: string; imgUrl: string }[];

 

 

리뷰모델

<review.entity.ts>

import { User } from 'src/auth/user.entity';
import { Recipe } from 'src/recipe/recipe.entity';
import {
  BaseEntity,
  Column,
  CreateDateColumn,
  DeleteDateColumn,
  Entity,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export class Review extends BaseEntity {
  @PrimaryGeneratedColumn()
  reviewId: number;

  @Column({ type: 'int' })
  star: number;

  @Column()
  comment: string;

  @CreateDateColumn({ type: 'timestamp' })
  createdAt: Date;

  @UpdateDateColumn({ type: 'timestamp' })
  updatedAt: Date;

  @DeleteDateColumn({ type: 'timestamp' })
  deletedAt: Date;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'id' })
  user: User;

  @ManyToOne(() => Recipe)
  @JoinColumn({ name: 'recipeId' })
  recipe: Recipe;
}

 

date의 경우 timestamp를 명시해주는 이유 - date type의 컬럼은 datetime형태로 저장됨

createDateColumn, updateDateColumn 키는 repositoy에 연계되어 지정하지 않더라도 생성, 업데이트 시 자동으로 생성됨

deleteDateColumn은 softdelete 할 경우 사용됨 / 실제 find할 경우 불러오지 않게됨

 

<review.dto.ts>

import { IsDate, IsNumber, IsString } from 'class-validator';

export class CreateReviewDto {
  @IsNumber()
  star: number;

  @IsString()
  comment: string;
}

 

<update-review.dto>

import { PartialType } from '@nestjs/mapped-types';
import { CreateReviewDto } from './create-review.dto';

export class UpdateReviewDto extends PartialType(CreateReviewDto) {}

 

<review.repositoy.ts>

import { InjectRepository } from '@nestjs/typeorm';
import { Review } from './review.entity';
import { DataSource, Repository } from 'typeorm';
import { CreateReviewDto } from './dto/create-review.dto';

export class ReviewRepository extends Repository<Review> {
  constructor(@InjectRepository(Review) private dataSource: DataSource) {
    super(Review, dataSource.manager);
  }
  async createReview(createReviewDto: CreateReviewDto): Promise<Review> {
    const { star, comment } = createReviewDto;

    const review = this.create({ star, comment });

    await this.save(review);
    return review;
  }
}

 

<review.service.ts>

import { Injectable, NotFoundException } from '@nestjs/common';
import { ReviewRepository } from './review.repositoy';
import { Review } from './review.entity';
import { CreateReviewDto } from './dto/create-review.dto';
import { UpdateReviewDto } from './dto/update-review.dto';

@Injectable()
export class ReviewService {
  constructor(private reviewRepositoty: ReviewRepository) {}

  async getAllReview(): Promise<Review[]> {
    return this.reviewRepositoty.find();
  }

  createReview(createReviewDto: CreateReviewDto): Promise<Review> {
    return this.reviewRepositoty.createReview(createReviewDto);
  }

  async getReviewById(reviewId: number): Promise<Review> {
    const found = await this.reviewRepositoty.findOneBy({ reviewId });

    if (!found) {
      throw new NotFoundException(
        `reviewId가 ${reviewId}인 리뷰를 찾을 수 없습니다.`,
      );
    }
    return found;
  }

  async deleteReview(reviewId: number): Promise<void> {
    const result = await this.reviewRepositoty.delete(reviewId);

    if (result.affected === 0) {
      throw new NotFoundException(`can't find reviewId ${reviewId}`);
    }
  }

  async updateReview(
    reviewId: number,
    updateReviewDto: UpdateReviewDto,
  ): Promise<Review> {
    const found = await this.reviewRepositoty.findOne({
      where: { reviewId },
    });

    if (!found) {
      throw new NotFoundException(
        `reviewId가 ${reviewId}인 리뷰를 찾을 수 없습니다.`,
      );
    }

    await this.reviewRepositoty.update(reviewId, updateReviewDto);
    const updateReview = await this.reviewRepositoty.findOne({
      where: { reviewId },
    });
    return updateReview;
  }
}

 

<review.controller.ts>

import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Patch,
  Post,
} from '@nestjs/common';
import { ReviewService } from './review.service';
import { Review } from './review.entity';
import { CreateReviewDto } from './dto/create-review.dto';
import { create } from 'domain';
import { UpdateReviewDto } from './dto/update-review.dto';

@Controller('review')
export class ReviewController {
  constructor(private reviewService: ReviewService) {}

  @Get('/')
  getAllTask(): Promise<Review[]> {
    return this.reviewService.getAllReview();
  }

  @Post('/insert')
  createReview(@Body() createReviewDto: CreateReviewDto): Promise<Review> {
    return this.reviewService.createReview(createReviewDto);
  }

  @Get('/:reviewId')
  getReviewById(@Param('reviewId') reviewId: number): Promise<Review> {
    return this.reviewService.getReviewById(reviewId);
  }

  @Patch('/:reviewId')
  updateReview(
    @Param('reviewId') reviewId: number,
    @Body() reviewData: UpdateReviewDto,
  ): Promise<Review> {
    return this.reviewService.updateReview(reviewId, reviewData);
  }

  @Delete('/:reviewId')
  deleteReview(@Param('reviewId', ParseIntPipe) reviewId): Promise<void> {
    return this.reviewService.deleteReview(reviewId);
  }
}

 

 

#엘리스트랙 #엘리스트랙후기 #리액트네이티브강좌 #온라인코딩부트캠프 #온라인코딩학원 #프론트엔드학원 #개발자국비지원 #개발자부트캠프 #국비지원부트캠프 #프론트엔드국비지원 #React #Styledcomponent #React Router Dom #Redux #Typescript #Javascript