Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rating and review #14

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed databases/dev.db
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_review" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"authorId" INTEGER NOT NULL,
"hotelId" INTEGER NOT NULL,
"rating" INTEGER NOT NULL,
"text" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "review_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "Users" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "review_hotelId_fkey" FOREIGN KEY ("hotelId") REFERENCES "Hotels" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_review" ("authorId", "hotelId", "id", "rating", "text") SELECT "authorId", "hotelId", "id", "rating", "text" FROM "review";
DROP TABLE "review";
ALTER TABLE "new_review" RENAME TO "review";
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:

- A unique constraint covering the columns `[authorId,hotelId]` on the table `review` will be added. If there are existing duplicate values, this will fail.

*/
-- CreateIndex
CREATE UNIQUE INDEX "review_authorId_hotelId_key" ON "review"("authorId", "hotelId");
2 changes: 2 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,6 @@ model review {
hotel hotel @relation(fields: [hotelId], references: [id])
rating Int
text String
createdAt DateTime @default(now())
// @@unique([authorId, hotelId]) it should be unique
}
106 changes: 106 additions & 0 deletions public/auth/front.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* Hero image */
.hero-image {
background-image: url("https://source.unsplash.com/1600x900/?hotel");
background-color: #000;
height: 50vh;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: relative;
}

.hero-text {
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}

/* Hotel cards */
.card {
border: none;
margin: 20px;
}

.card .card-img-top {
object-fit: cover;
height: 200px;
}

.card-title {
font-size: 24px;
font-weight: 500;
}

.card-text {
margin-top: 10px;
margin-bottom: 10px;
}


.rating {
color:red
}

/* Star rating */
.stars {
display: inline-block;
font-size: 18px;
color: #ffd700;
}

.stars i {
margin-right: 5px;
}

.half {
position: relative;
}

.half::before {
content: "\f089";
font-family: "Font Awesome 5 Free";
font-weight: 900;
position: absolute;
left: 0;
color: #777;
}

/* change color of the stars according to rating data */
.stars-0,
.stars-1,
.stars-2,
.stars-3,
.stars-4,
.stars-5 {
color: #b3b3b3;
}

.stars-1 i:nth-child(-n + 1),
.stars-2 i:nth-child(-n + 2),
.stars-3 i:nth-child(-n + 3),
.stars-4 i:nth-child(-n + 4),
.stars-5 i:nth-child(-n + 5) {
color: #ffd700;
}

.stars-0.half,
.stars-1.half,
.stars-2.half,
.stars-3.half,
.stars-4.half,
.stars-5.half {
color: #ffd700;
}

.stars-0.half::before,
.stars-1.half::before,
.stars-2.half::before,
.stars-3.half::before,
.stars-4.half::before,
.stars-5.half::before {
color: #b3b3b3;
}

44 changes: 44 additions & 0 deletions public/auth/script/front.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
let hotelurl;
hotelurl = 'http://localhost:3000/upload/';
JavaScript:

$(document).ready(() => {
// fetch data from API and generate hotel cards
fetch("http://localhost:3000/review/a",{
method:'Put'
})
.then(response => response.json())
.then(data => {
const hotelCards = data.map(hotel => {
// calculate star rating data
const rating = hotel.averageRating;
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 >= 0.5;
const emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0);
// generate star rating HTML
const starRatingHtml = `
<div class="stars stars-${fullStars}${hasHalfStar ? " half" : ""}">
${Array(fullStars).fill().map(() => '<i class="fas fa-star"></i>').join("")}
${hasHalfStar ? '<i class="fas fa-star-half"></i>' : ""}
${Array(emptyStars).fill().map(() => '<i class="far fa-star"></i>').join("")}
</div>
`;
// generate hotel card HTML

return `
<div class="col-12 col-md-6 col-lg-4">
<div class="card">
<img src="${hotelurl+hotel.hotel_image}" class="card-img-top" alt="${hotel.hotel_name}">
<div class="card-body">
<h5 class="card-title">${hotel.hotel_name}</h5>
<p class="card-text">${hotel.user_name}</p>
<div class="rating">${starRatingHtml}</div>
</div>
</div>
</div>
`;
}).join("");
// insert hotel cards into DOM
$("#hotel-cards").html(hotelCards);
});
});
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ async function bootstrap() {
AppModule,
{cors: true}
);
app.enableCors();

app.useGlobalPipes(
new ValidationPipe({
Expand Down
15 changes: 14 additions & 1 deletion src/review/review.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Body, Controller, Get, Param, ParseIntPipe, Patch, Post, Req, UseGuards } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, Put, Req, UseGuards } from '@nestjs/common';
import { JwtGuard } from 'src/auth/jwt.guard';
import { reviewDto, updateReviewDto } from './review.dto';
import { ReviewService } from './review.service';
Expand Down Expand Up @@ -42,7 +42,20 @@ export class ReviewController {
}


@UseGuards(JwtGuard)
@Delete('/:id')
async deleteReview(@Param('id', new ParseIntPipe()) reviewId:number, @Req() req: any){
return await this.reviewService.deleteReview(reviewId,req.user.id)
}
@Get('average/:id')
async getAverageRating(@Param('id', new ParseIntPipe()) hotelId:number){
return await this.reviewService.getAverageRating(hotelId)
}

@Put('a')
async getAllHotels(){
return await this.reviewService.getAllHotels()
}



Expand Down
2 changes: 2 additions & 0 deletions src/review/review.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export class updateReviewDto{
@IsNotEmpty()
hotelId:number
}


91 changes: 79 additions & 12 deletions src/review/review.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { All, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
import { All, ForbiddenException, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from 'src/prisma/prisma.service';
import { reviewDto, updateReviewDto } from './review.dto'
Expand All @@ -8,17 +8,34 @@ export class ReviewService {
constructor(private prisma:PrismaService){}

async createReview(dto: reviewDto, userId: number) {
let newReview = await this.prisma.review.create({
data: {
authorId: userId,
hotelId:dto.hotelId,
rating:dto.rating,
text:dto.text
try {
let hotel = await this.prisma.hotel.findUnique({
where:{
id:dto.hotelId
}
})
if (!hotel){
throw new NotFoundException(`Hotel with ID ${dto.hotelId} not found.`);
}
});
return newReview
}

let newReview = await this.prisma.review.create({
data: {
authorId: userId,
hotelId:dto.hotelId,
rating:dto.rating,
text:dto.text
}
});
return {
success:true,
data:newReview
}
} catch (error) {
if (error.code === "P2002") {
return { success: false, message: "You have already reviewed this hotel." };
}
return { success: false, message: error.message };
}
}
async getAllReviews(){
let AllReviews = await this.prisma.review.findMany();
return {
Expand Down Expand Up @@ -63,6 +80,56 @@ export class ReviewService {

}


async deleteReview(id: number, userId: number): Promise<reviewDto> {
// Check if review with given id exists
const review = await this.prisma.review.findUnique({ where: { id } });
if (!review) {
throw new NotFoundException(`Review with id ${id} not found`);
}

// Check if the user is the author of the review
if (review.authorId !== userId) {
throw new ForbiddenException('You are not authorized to delete this review');
}

// Delete the review
return this.prisma.review.delete({ where: { id } });
}


async getAverageRating(hotelId:number):Promise<number> {
const reviews = await this.prisma.review.findMany({
where: {
hotelId: hotelId,
},
select: {
rating: true,
},
});
if (!reviews){
return 0;
}

const numReviews = reviews.length;
const sumRatings = reviews.reduce((acc, review) => acc + review.rating, 0);

if (numReviews === 0) {
return 0;
} else {
const averageRating = sumRatings / numReviews;
await this.prisma.hotel.update({
where: { id: hotelId },
data: { averageRating: averageRating },
});
return averageRating;
}
}

async getAllHotels(){
return this.prisma.hotel.findMany()
}
}




Loading