diff --git a/Dockerfile b/Dockerfile index 0413e6d9203b21d4bc4fe7acca05043bd00f5048..aa095c6c88df9037de6fac29aa1815be1c9bccf5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,6 @@ COPY prisma ./prisma RUN npm install -EXPOSE 3000 +EXPOSE 3010 CMD ["npm", "start"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c7f0e61085f2fbab82b307410672d9958d2621f7..42c170108f40c57109da8c6dd8d83f087b9b966b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: app: build: . ports: - - '3000:3000' + - '3010:3000' depends_on: - db env_file: @@ -13,11 +13,11 @@ services: db: image: mysql:8.0 environment: - - MYSQL_ROOT_PASSWORD={DB_PASSWORD} - - MYSQL_DATABASE={DB_NAME} - - MYSQL_USERNAME={DB_USER} - - MYSQL_PASSWORD={DB_PASSWORD} + - MYSQL_ROOT_PASSWORD=123456 + - MYSQL_DATABASE=rest_prisma + - MYSQL_USERNAME=root + - MYSQL_PASSWORD=123456 ports: - '3307:3306' volumes: - - ./mysql-data:/var/lib/mysql \ No newline at end of file + - ./db:/docker-entrypoint-initdb.d \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6cfbfe54d530d0b8a847c350cf511d3840603a39..1f563823720eed825052bb0edc210c66c2c9051b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "http-status-codes": "^2.3.0", "joi": "^17.11.0", "jsonwebtoken": "^9.0.2", "mysql2": "^3.6.2", @@ -23,6 +24,7 @@ "prisma": "^5.5.2" }, "devDependencies": { + "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.20", "@types/jsonwebtoken": "^9.0.4", "@types/password-hash": "^1.2.23", @@ -124,6 +126,15 @@ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, + "node_modules/@types/bcrypt": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz", + "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.4", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", @@ -1144,6 +1155,11 @@ "node": ">= 0.8" } }, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==" + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", diff --git a/package.json b/package.json index 9dc0eae7c86c1d89168822ffd6e8778eb5b3192e..4b59bf17432817df8cf07f613f061af6e18f59c0 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", + "http-status-codes": "^2.3.0", "joi": "^17.11.0", "jsonwebtoken": "^9.0.2", "mysql2": "^3.6.2", @@ -26,6 +27,7 @@ "prisma": "^5.5.2" }, "devDependencies": { + "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.20", "@types/jsonwebtoken": "^9.0.4", "@types/password-hash": "^1.2.23", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f2a3fefb6d5ae056350f16c2e4bde81343f4fedb..74ad8ec8da9e05e7c6b360d9c92e7c765ea5e824 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -18,11 +18,21 @@ model psikolog { } model reservation { - reservation_id Int @id @default(autoincrement()) + reservation_id Int @id @default(autoincrement()) psikolog_id Int user_id Int - datetime DateTime @db.DateTime(0) - psikolog psikolog @relation(fields: [psikolog_id], references: [psikolog_id], onDelete: Cascade, map: "psikolog_id") + datetime DateTime @db.DateTime(0) + feedback feedback[] + psikolog psikolog @relation(fields: [psikolog_id], references: [psikolog_id], onDelete: Cascade, map: "psikolog_id") @@index([psikolog_id], map: "psikolog_id_idx") } + +model feedback { + feedback_id Int @id @default(autoincrement()) + feedback_content String @db.VarChar(255) + reservation_id Int? + reservation reservation? @relation(fields: [reservation_id], references: [reservation_id], onDelete: Cascade, map: "reservation_id") + + @@index([reservation_id], map: "reservation_id_idx") +} diff --git a/src/app.ts b/src/app.ts index 4fad26004ff278db65c83c2846cbaa57d99d7957..622247e82b33668e04b5568e1b1e87ef1a322ea2 100644 --- a/src/app.ts +++ b/src/app.ts @@ -13,7 +13,7 @@ var corsOptions = { methods: ['GET', 'PUT', 'POST', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], optionsSuccessStatus: 200, - allowedOrigins: ['http://localhost:3001'] + allowedOrigins: ['http://localhost:3000'] }; const accessValidation = (req: any, res: any, next: any) => { const {authorization} = req.headers; diff --git a/src/models/feedback/index.ts b/src/models/feedback/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..f82abddb0b52114f7177f8f277d593ba5ef12d66 --- /dev/null +++ b/src/models/feedback/index.ts @@ -0,0 +1,49 @@ +import {feedback} from './type'; + +export const addFeedback = async (mysql: any, feedback_content: string, reservation_id: number) => { + console.log('Adding feedback to database'); + try { + const prisma = await mysql.prisma(); + await prisma.feedback.create({ + data: { + feedback_content: feedback_content, + reservation_id: reservation_id, + } + }); + + console.log('Feedback added successfully'); + } catch (error) { + console.error('Error adding feedback:', error); + throw new Error('Failed to add feedback'); // You can customize this message + } +} + +export const deleteFeedback = async (mysql: any, feedback_id: number) => { + try { + const prisma = await mysql.prisma(); + await prisma.feedback.delete({ + where: { + feedback_id: feedback_id, + } + }); + } catch (error) { + console.error('Error deleting feedback:', error); + throw new Error('Failed to delete feedback'); // You can customize this message + } +} + +export const showList = async (mysql: any, feedback_id: number) => { + try { + const prisma = await mysql.prisma(); + const feedback = await prisma.feedback.findMany({ + where: { + feedback_id: feedback_id, + }, + }); + console.log('Showing feedback', feedback); + return feedback; + } catch (error) { + console.error('Error in findFeedbackById:', error); + throw error; + } +} \ No newline at end of file diff --git a/src/models/feedback/type.ts b/src/models/feedback/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..adc9d99a81ae3ad06345b5681ef2850ceca84c8c --- /dev/null +++ b/src/models/feedback/type.ts @@ -0,0 +1,4 @@ +export interface feedback { + feedback_content: string; + reservation_id: number; +} \ No newline at end of file diff --git a/src/models/psikolog/index.ts b/src/models/psikolog/index.ts index f4c4dae2253b0a7b693c99cd48ae7440ecfa4b9a..756be2626ab01ea2123f1088caca7e011f7220d5 100644 --- a/src/models/psikolog/index.ts +++ b/src/models/psikolog/index.ts @@ -116,4 +116,15 @@ export const bookPsikolog = async (msql: any, id: number, email: string) => { } }); return book; +} + +export const reservationFeedback = async (msql: any, id: number, feedback: string) => { + const prisma = await msql.prisma(); + const feedbacks = await prisma.reservation.update({ + where: { reservation_id: id }, + data: { + reservation_feedback: feedback, + } + }); + return feedbacks; } \ No newline at end of file diff --git a/src/routes/psikolog.ts b/src/routes/psikolog.ts index a3d55caed4d194d9cc69d5a2d1f20f9001c30e85..feeaf792a71ffb916ce70e7981c720ebd8451e38 100644 --- a/src/routes/psikolog.ts +++ b/src/routes/psikolog.ts @@ -1,6 +1,6 @@ import { Router, Request, Response } from 'express'; import { logger } from '../middlewares'; -import { showPsikologId, updateProfile } from '../service/psikolog'; +import { delFeedback, giveFeedback, showPsikologId, updateProfile } from '../service/psikolog'; import { showPsikolog } from '../models/psikolog'; import mysql from '../infrastructure/database/mysql'; import { login, register } from '../handler/psikolog'; @@ -17,6 +17,20 @@ router.post('/register', validateRequest({body: jRegisterReq}),register); router.post('/login', validateRequest({body: jLoginReq}), login); +router.post('/feedback/:id', async (req: Request, res: Response) => { + try { + const feedback = await giveFeedback( + parseInt(req.params.id), + req.body.feedback_content, + ); + res.send({ message: 'Feedback added successfully', data: feedback }); + } catch (error) { + console.error('Error:', error); + res.status(500).send({ message: 'Internal Server Error' }); + } +} +); + router.get('/user/:id', async (req: Request, res: Response) => { try { const psikolog = await showPsikologId(parseInt(req.params.id)); @@ -62,4 +76,15 @@ router.put('/update/:id', async (req: Request, res: Response) => { console.error('Error:', error); res.status(500).send({ message: 'Internal Server Error' }); } - }); \ No newline at end of file + }); + +router.delete('/delete/:id', async (req: Request, res: Response) => { + try { + const psikolog = await delFeedback(parseInt(req.params.id)); + + return res.send({ message: 'Feedback deleted', data: psikolog }); + } catch (error) { + console.error('Error:', error); + return res.status(500).send({ message: 'Internal Server Error' }); + } +}); \ No newline at end of file diff --git a/src/service/psikolog.ts b/src/service/psikolog.ts index 06dd12a61541c5014e00765f753ac95ca4501fc3..9276015b86749f55d1f22831e677a91890adc7d1 100644 --- a/src/service/psikolog.ts +++ b/src/service/psikolog.ts @@ -1,6 +1,7 @@ import mysql from "../infrastructure/database/mysql"; import { psikolog } from "../models/psikolog/type"; import { addPsikolog, findPsikologByEmail, findPsikologById, updatePsikolog } from "../models/psikolog"; +import { addFeedback, deleteFeedback, showList } from "../models/feedback"; const add = async ( psikolog_email: string, @@ -97,6 +98,28 @@ const updateProfile = async ( } }; +const giveFeedback = async ( + reservation_id: number, + feedback_content: string,) => { + await mysql.connect(); + const feedback = await addFeedback(mysql, feedback_content, reservation_id); + return feedback; + } + +const delFeedback = async ( + feedback_id: number) => { + await mysql.connect(); + const feedback = await deleteFeedback(mysql, feedback_id); + return feedback; + } + +const showFeedbackByReservationId = async ( + feedback_id: number) => { + await mysql.connect(); + const feedback = await showList(mysql, feedback_id); + return feedback; + } + -export{ add, showPsikologId, updateProfile }; \ No newline at end of file +export{ add, showPsikologId, updateProfile, giveFeedback, delFeedback, showFeedbackByReservationId }; \ No newline at end of file