diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8609552e3eb997ffe5e844645972bc9a1c37bfa4..f2a3fefb6d5ae056350f16c2e4bde81343f4fedb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -7,21 +7,22 @@ datasource db { url = env("DATABASE_URL") } -model chat { - chat_id Int @id @default(autoincrement()) - psikolog_id Int - user_id String @db.VarChar(45) - psikolog psikolog @relation(fields: [psikolog_id], references: [psikolog_id], onDelete: Cascade, map: "psikolog_id") - - @@index([psikolog_id], map: "psikolog_id_idx") +model psikolog { + psikolog_id Int @id @default(autoincrement()) + psikolog_email String @db.VarChar(45) + psikolog_name String @db.VarChar(45) + psikolog_password String @db.VarChar(255) + psikolog_klinik String? @db.VarChar(45) + psikolog_phone String @db.VarChar(45) + reservation reservation[] } -model psikolog { - psikolog_id Int @id @default(autoincrement()) - psikolog_email String @db.VarChar(45) - psikolog_name String @db.VarChar(45) - psikolog_password String @db.VarChar(255) - psikolog_klinik String? @db.VarChar(45) - psikolog_phone String @db.VarChar(45) - chat chat[] +model reservation { + 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") + + @@index([psikolog_id], map: "psikolog_id_idx") } diff --git a/src/app.ts b/src/app.ts index 4a232766854b9b2214e801f27a0efc2dc3fcec9c..82b7006791b74142f24d4703a0ad7ac12d07d727 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,5 @@ import express from 'express'; -import {psikologRouter} from './routes'; +import {psikologRouter, userRouter} from './routes'; import { logger } from './middlewares'; const app = express(); @@ -26,6 +26,8 @@ app.use(logger); app.use(cors(corsOptions)); app.use(express.json()); app.use('/psikolog', psikologRouter); +app.use('/user', userRouter); + app.use((req, res, next) => { res.send({message: 'Hello world!'}); diff --git a/src/handler/book/index.ts b/src/handler/book/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3dc92ce191c802e6c0be01b4b5b73607c386636 --- /dev/null +++ b/src/handler/book/index.ts @@ -0,0 +1,17 @@ +import { Request } from "express"; +import { makeReservation } from "../../service/book"; + +const bookingPsikolog = async (req: Request) => { + try{ + const user_id = req.body.user_id; + const psikolog_id = req.body.psikolog_id; + const datetime = req.body.datetime; + + const result = await makeReservation(user_id, psikolog_id, datetime); + console.log("the result is " + result); + } catch (error) { + console.error('Error:', error); + throw error; + }} + +export { bookingPsikolog }; diff --git a/src/handler/psikolog/index.ts b/src/handler/psikolog/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..ed9b02b72aac0e6d3be2615decb766b173136f29 --- /dev/null +++ b/src/handler/psikolog/index.ts @@ -0,0 +1,38 @@ +import { Request, Response, NextFunction } from "express"; +import { jLoginReq, jLoginRes } from "./type"; +import { loginPsikolog, registerPsikolog } from "../../service/auth"; +import * as HttpStatus from 'http-status-codes'; +import { buildResponse } from "../../util/response"; + +const login = async (req: Request, res: Response, next: NextFunction) => { + try { + const psikolog_email = req.body.psikolog_email; + const psikolog_password = req.body.psikolog_password; + + console.log("the user is " + psikolog_email + " " + psikolog_password); + const result = await loginPsikolog(psikolog_email, psikolog_password); + console.log("the result is " + result); + } + catch (error) { + next(error); + res.send("failed"); + } +} + +const register = async (req: Request, res: Response, next: NextFunction) => { + try { + const result = await registerPsikolog( + req.body.psikolog_email, + req.body.psikolog_name, + req.body.psikolog_password, + req.body.psikolog_phone, + req.body.psikolog_klinik, + ); + console.log("the result is " + result); + } catch (error) { + console.error('Error:', error); + return res.status(500).send({ message: 'Internal Server Error' }); + } +}; + +export { login, register }; diff --git a/src/handler/psikolog/type.ts b/src/handler/psikolog/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..b68e4d0df4b69defe7396e8ba962ebc773bcc2f6 --- /dev/null +++ b/src/handler/psikolog/type.ts @@ -0,0 +1,24 @@ +import Joi from 'joi'; + +const jLoginReq = Joi.object({ + psikolog_email: Joi.string().email().required(), + psikolog_password: Joi.string().required(), + }); + +const jLoginRes = Joi.object({ + token: Joi.string().required(), + }); + +const jRegisterReq = Joi.object({ + psikolog_email: Joi.string().email().required(), + psikolog_password: Joi.string().required(), + psikolog_name: Joi.string().required(), + psikolog_phone: Joi.string().required(), + psikolog_klinik: Joi.string().required(), + }); + +const jRegisterRes = Joi.object({ + token: Joi.string().required(), + }); + +export { jLoginReq, jLoginRes, jRegisterReq, jRegisterRes }; \ No newline at end of file diff --git a/src/handler/user/index.ts b/src/handler/user/index.ts index 82d1fcf76e1fdd694feeae839a4fd30eb26f01f5..47cb7c87f3b3d8ea590c133079266866f5047551 100644 --- a/src/handler/user/index.ts +++ b/src/handler/user/index.ts @@ -1,49 +1,2 @@ -import { Request, Response, NextFunction } from "express"; -import { jLoginReq, jLoginRes } from "./type"; -import { loginPsikolog, registerPsikolog } from "../../service/auth"; -import * as HttpStatus from 'http-status-codes'; -import { buildResponse } from "../../util/response"; - -const login = async (req: Request, res: Response, next: NextFunction) => { - try { - const psikolog_email = req.body.psikolog_email; - const psikolog_password = req.body.psikolog_password; - - // const user = { - // psikolog_email: psikolog_email, - // psikolog_password: psikolog_password - // }; - console.log("the user is " + psikolog_email + " " + psikolog_password); - const result = await loginPsikolog(psikolog_email, psikolog_password); - console.log("the result is " + result); - } - catch (error) { - next(error); - res.send("failed"); - } -} - -const register = async (req: Request, res: Response, next: NextFunction) => { - try { - const result = await registerPsikolog( - req.body.psikolog_email, - req.body.psikolog_name, - req.body.psikolog_password, - req.body.psikolog_phone, - req.body.psikolog_klinik, - ); - - // const statusCode = - // result === null - // ? HttpStatus.StatusCodes.BAD_REQUEST - // : HttpStatus.StatusCodes.OK; - - // buildResponse(res, statusCode, result); - console.log("the result is " + result); - } catch (error) { - console.error('Error:', error); - return res.status(500).send({ message: 'Internal Server Error' }); - } -}; - -export { login, register }; +const bookPsikolog = async (req: Request, res: Response) => { +}; \ No newline at end of file diff --git a/src/handler/user/type.ts b/src/handler/user/type.ts index b68e4d0df4b69defe7396e8ba962ebc773bcc2f6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/src/handler/user/type.ts +++ b/src/handler/user/type.ts @@ -1,24 +0,0 @@ -import Joi from 'joi'; - -const jLoginReq = Joi.object({ - psikolog_email: Joi.string().email().required(), - psikolog_password: Joi.string().required(), - }); - -const jLoginRes = Joi.object({ - token: Joi.string().required(), - }); - -const jRegisterReq = Joi.object({ - psikolog_email: Joi.string().email().required(), - psikolog_password: Joi.string().required(), - psikolog_name: Joi.string().required(), - psikolog_phone: Joi.string().required(), - psikolog_klinik: Joi.string().required(), - }); - -const jRegisterRes = Joi.object({ - token: Joi.string().required(), - }); - -export { jLoginReq, jLoginRes, jRegisterReq, jRegisterRes }; \ No newline at end of file diff --git a/src/models/book/index.ts b/src/models/book/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..f9a4f92d7bfb6df3131dc5a5e61e679180a0a690 --- /dev/null +++ b/src/models/book/index.ts @@ -0,0 +1,36 @@ +import {Reservation} from './type'; + +export const reservedPsikolog =async (msql:any, reserved: Reservation) => { + console.log('Adding reservation to database'); + try{ + const prisma = await msql.prisma(); + await prisma.reservation.create({ + data: { + psikolog_id: reserved.psikolog_id, + user_id: reserved.user_id, + datetime : reserved.datetime, + } + }); + } catch (error){ + console.error('Error:', error); + throw error; + } +} + +export const showReservedPsikolog = async (msql: any, id: number) => { + console.log('Showing id', id); + try { + const prisma = await msql.prisma(); + const psikolog = await prisma.reservation.findMany({ + where: { + psikolog_id: id, + }, + }); + console.log('Id', id); + console.log('Showing reserved psikolog', psikolog); + return psikolog; + } catch (error) { + console.error('Error in findPsikologById:', error); + throw error; + } +} diff --git a/src/models/book/type.ts b/src/models/book/type.ts new file mode 100644 index 0000000000000000000000000000000000000000..769801b1ddd50a43d2a42361c0997ea9e5c25cc7 --- /dev/null +++ b/src/models/book/type.ts @@ -0,0 +1,5 @@ +export interface Reservation { + psikolog_id: number; + user_id: number; + datetime: string; +} \ No newline at end of file diff --git a/src/models/psikolog/index.ts b/src/models/psikolog/index.ts index 86e6c9f7e21c593b7aea5f6ab42948829aebbe62..f02d2cbe124528ffc71b6a24176a1b5bb844e838 100644 --- a/src/models/psikolog/index.ts +++ b/src/models/psikolog/index.ts @@ -152,6 +152,17 @@ const updatePsikologEmail = async (msql: any, id: number, email: string) => { return psikolog; } +const bookPiskolog = async (msql: any, id: number, email: string) => { + const prisma = await msql.prisma(); + const book = await prisma.book.create({ + data: { + psikolog_id: id, + user_email: email, + } + }); + return book; +} + export{ addPsikolog, showPsikolog, diff --git a/src/models/user/index.ts b/src/models/user/index.ts deleted file mode 100644 index 6478a5fc3f03acabc8c10961e8df52c5d9cdf404..0000000000000000000000000000000000000000 --- a/src/models/user/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { User } from './type'; - -const addUser = async (mysql: any, user: User) => { - const prisma = await mysql.prisma(); - await prisma.user.create({ - data: { - name: user.name, - email: user.email, - password: user.password, - phonenumber: user.phonenumber, - gender: user.gender - } - }); - } - -const findUserByEmail = async (mysql: any, email: string) => { - const prisma = await mysql.prisma(); - const user = await prisma.user.findUnique({ - where: { - email: email, - }, - }); - return user; -} - -const findUserById = async (mysql: any, id: number) => { - const prisma = await mysql.prisma(); - const user = await prisma.user.findUnique({ - where: { - id: id, - }, - }); - return user; -} - -const findUserByPhonenumber = async (mysql: any, phonenumber: number) => { - const prisma = await mysql.prisma(); - const user = await prisma.user.findUnique({ - where: { - phonenumber: phonenumber, - }, - }); - return user; -} - -export{ - addUser, - findUserByEmail, - findUserById, - findUserByPhonenumber -} ; \ No newline at end of file diff --git a/src/models/user/type.ts b/src/models/user/type.ts deleted file mode 100644 index d8d4577d2c5174d173242223be6e34d628f35ba2..0000000000000000000000000000000000000000 --- a/src/models/user/type.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface User { - name: string; - email: string; - password: string; - phonenumber: number; - gender: string; -} \ No newline at end of file diff --git a/src/routes/index.ts b/src/routes/index.ts index 606a1da707147424731cc06cafc19ad85aa736bb..a6776446021d6d9789a34fa2f219da0c45b04ed2 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1 +1,2 @@ -export {router as psikologRouter} from './psikolog'; \ No newline at end of file +export {router as psikologRouter} from './psikolog'; +export {router as userRouter} from './user'; \ No newline at end of file diff --git a/src/routes/psikolog.ts b/src/routes/psikolog.ts index dd61e211eb516c8b43b017c6687ed44ac975c6b0..670325adfb7d847521e39b4b220982cca0ae7ef1 100644 --- a/src/routes/psikolog.ts +++ b/src/routes/psikolog.ts @@ -3,10 +3,10 @@ import { logger } from '../middlewares'; import { showPsikologId } from '../service/psikolog'; import { showPsikolog } from '../models/psikolog'; import mysql from '../infrastructure/database/mysql'; -import { loginPsikolog, registerPsikolog } from "../service/auth"; -import { login, register } from '../handler/user'; +import { login, register } from '../handler/psikolog'; import validateRequest from '../util/validate'; -import { jLoginReq, jRegisterReq } from '../handler/user/type'; +import { jLoginReq, jRegisterReq } from '../handler/psikolog/type'; +import { listReservation } from '../service/book'; export const router = Router(); @@ -17,22 +17,6 @@ router.post('/register', validateRequest({body: jRegisterReq}),register); router.post('/login', validateRequest({body: jLoginReq}), login); -router.get('/consultation', async (req: Request, res: Response) => { - try { - const psikolog = await showPsikolog(mysql); - - if (!psikolog) { - return res.status(404).send({ message: 'Psikolog not found' }); - } - - return res.send({ message: 'Show all psikolog', data: psikolog }); - } catch (error) { - console.error('Error:', error); - return 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)); @@ -47,3 +31,18 @@ router.get('/user/:id', async (req: Request, res: Response) => { res.status(500).send({ message: 'Internal Server Error' }); } }); + +router.get('/booked/:id', async (req: Request, res: Response) => { + try { + const psikolog = await listReservation(parseInt(req.params.id)); + + if (!psikolog) { + return res.status(404).send({ message: 'Psikolog not found' }); + } + + return res.send({ message: 'Show all psikolog', 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/routes/user.ts b/src/routes/user.ts new file mode 100644 index 0000000000000000000000000000000000000000..fddda16e6a58b2ac1c8d3a9d2bef885eadecff57 --- /dev/null +++ b/src/routes/user.ts @@ -0,0 +1,39 @@ +import { Router, Request, Response } from 'express'; +import { logger } from "../middlewares"; +import { showPsikolog } from '../models/psikolog'; +import mysql from '../infrastructure/database/mysql'; +import { validateApiKey } from '../util/apikey'; +import { bookingPsikolog } from '../handler/book'; + + +export const router = Router(); + +router.use(logger); + + +router.get('/consultation', async (req: Request, res: Response) => { + try { + const psikolog = await showPsikolog(mysql); + + if (!psikolog) { + return res.status(404).send({ message: 'Psikolog not found' }); + } + + return res.send({ message: 'Show all psikolog', data: psikolog }); + } catch (error) { + console.error('Error:', error); + return res.status(500).send({ message: 'Internal Server Error' }); + } + }); + +router.post('/reservation', + async (req: Request, res: Response) => { + try { + const result = await bookingPsikolog(req); + res.send({ message: 'Booking success', data: result }); + } 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/book.ts b/src/service/book.ts new file mode 100644 index 0000000000000000000000000000000000000000..85a59d41df5348ff8eac50b65e7983e44f942d33 --- /dev/null +++ b/src/service/book.ts @@ -0,0 +1,41 @@ +import msql from "../infrastructure/database/mysql"; +import { Reservation } from "../models/book/type"; +import { reservedPsikolog, showReservedPsikolog } from "../models/book"; + +const makeReservation = async ( + psikolog_id: number, + user_id: number, + datetime: string, +) => { + try { + await msql.connect(); + const reservation: Reservation = { + psikolog_id: psikolog_id, + user_id: user_id, + datetime: datetime, + }; + await reservedPsikolog(msql, reservation); + } catch (error) { + console.error('Error:', error); + throw error; + } finally { + await msql.disconnect(); + } +} + +const listReservation = async (psikolog_id: number) => { + try { + await msql.connect(); + console.log('Showing reserved psikoolog', psikolog_id); + const reservation = await showReservedPsikolog(msql, psikolog_id); + console.log('Showing reserved reservation', reservation); + return reservation; + } catch (error) { + console.error('Error:', error); + throw error; + } finally { + await msql.disconnect(); + } +} + +export {makeReservation, listReservation}; \ No newline at end of file diff --git a/src/util/apikey.ts b/src/util/apikey.ts new file mode 100644 index 0000000000000000000000000000000000000000..9cdfb98e920f9ca7cc04164598a4c33ea35d0779 --- /dev/null +++ b/src/util/apikey.ts @@ -0,0 +1,35 @@ +import * as httpStatus from "http-status-codes"; +import { Request as ExpressRequest, Response, NextFunction } from 'express'; +import { buildResponse } from './response'; +import jwt, { JwtPayload } from 'jsonwebtoken'; + +interface MyJwtPayload extends JwtPayload { + role: 'user' | 'psikolog'; +} + +// Extend the Express Request interface +interface Request extends ExpressRequest { + user?: MyJwtPayload; +} + +const validateApiKey = () =>{ + return (req: Request, res: Response, next: NextFunction) => { + const apiKey = req.headers['x-api-key'] as string; + if (!apiKey) { + return buildResponse(res, httpStatus.StatusCodes.UNAUTHORIZED, 'API key is missing'); + } + + try { + const decoded = jwt.verify(apiKey, process.env.JWT_SECRET as string) as MyJwtPayload; + if (!['user', 'psikolog'].includes(decoded.role)) { + return buildResponse(res, httpStatus.StatusCodes.UNAUTHORIZED, 'Invalid role'); + } + req.user = decoded; + next(); + } catch (err) { + return buildResponse(res, httpStatus.StatusCodes.UNAUTHORIZED, 'Invalid API key'); + } +}; +} + +export { validateApiKey }; \ No newline at end of file