diff --git a/src/controllers/customer.js b/src/controllers/customer.js index 775cfb42..e33ace5e 100644 --- a/src/controllers/customer.js +++ b/src/controllers/customer.js @@ -1,5 +1,5 @@ const { PrismaClientKnownRequestError } = require("@prisma/client") -const { createCustomerDb } = require('../domains/customer.js') +const { createCustomerDb, updateCustomerDb } = require('../domains/customer.js') const createCustomer = async (req, res) => { const { @@ -13,26 +13,11 @@ const createCustomer = async (req, res) => { error: "Missing fields in request body" }) } - - // Try-catch is a very common way to handle errors in JavaScript. - // It allows us to customise how we want errors that are thrown to be handled. - // Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch - - // Here, if Prisma throws an error in the process of trying to create a new customer, - // instead of the Prisma error being thrown (and the app potentially crashing) we exit the - // `try` block (bypassing the `res.status` code) and enter the `catch` block. try { const createdCustomer = await createCustomerDb(name, phone, email) res.status(201).json({ customer: createdCustomer }) } catch (e) { - // In this catch block, we are able to specify how different Prisma errors are handled. - // Prisma throws errors with its own codes. P2002 is the error code for - // "Unique constraint failed on the {constraint}". In our case, the {constraint} is the - // email field which we have set as needing to be unique in the prisma.schema. - // To handle this, we return a custom 409 (conflict) error as a response to the client. - // Prisma error codes: https://www.prisma.io/docs/orm/reference/error-reference#common - // HTTP error codes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses if (e instanceof PrismaClientKnownRequestError) { if (e.code === "P2002") { return res.status(409).json({ error: "A customer with the provided email already exists" }) @@ -43,6 +28,32 @@ const createCustomer = async (req, res) => { } } +const updateCustomer = async (req, res) => { + const { + name, + phone, + email + } = req.body + const id = parseInt(req.params.id) + + try { + const updatedCustomer = await updateCustomerDb(id, name, phone, email) + + res.status(201).json({ customer: updatedCustomer }) + } catch (e) { + if (e instanceof PrismaClientKnownRequestError) { + if (e.code === "P2002") { + return res.status(409).json({ error: "A customer with the provided email already exists" }) + } + } + + console.error(e) + + res.status(500).json({ error: e.message }) + } +} + module.exports = { - createCustomer + createCustomer, + updateCustomer } diff --git a/src/controllers/movies.js b/src/controllers/movies.js new file mode 100644 index 00000000..c7077a8a --- /dev/null +++ b/src/controllers/movies.js @@ -0,0 +1,68 @@ +const { + getMoviesDb, + getMovieByIdDb, + createMovieDb, + updateMovieDb +} = require('../domains/movies') + +const getMovies = async (req, res) => { + try { + const movies = await getMoviesDb() + res.status(200).json({ movies: movies }) + } catch (e) { + console.log(e) + res.status(500).json({ error: e.message }) + } +} + +const getMovieById = async (req, res) => { + const id = parseInt(req.params.id) + + try { + const movie = await getMovieByIdDb(id) + res.status(200).json({ movie }) + } catch (e) { + console.error(e) + res.status(500).json({ error: e.message }) + } +} + +const createMovie = async (req, res) => { + const { title, runtimeMins } = req.body + + if (!title || !runtimeMins) { + return res.status(400).json({ + error: "Missing fields in request body" + }) + } + + try { + const createdMovie = await createMovieDb(title, runtimeMins) + + res.status(201).json({ movie: createdMovie }) + } catch (e) { + console.error(e) + res.status(500).json({ error: e.message }) + } +} + +const updateMovie = async (req, res) => { + const { title, runtimeMins } = req.body + const id = parseInt(req.params.id) + + try { + const updatedMovie = await updateMovieDb(id, title, runtimeMins) + + res.status(201).json({ movie: updatedMovie }) + } catch (e) { + console.error(e) + res.status(500).json({ error: e.message }) + } +} + +module.exports = { + getMovies, + getMovieById, + createMovie, + updateMovie +} \ No newline at end of file diff --git a/src/controllers/screens.js b/src/controllers/screens.js new file mode 100644 index 00000000..6efedfbd --- /dev/null +++ b/src/controllers/screens.js @@ -0,0 +1,28 @@ +const { + createScreenDb +} = require('../domains/screens') + +const createScreen = async (req, res) => { + const { number } = req.body + + console.log(req.body) + + if (!number) { + return res.status(400).json({ + error: "Missing fields in request body" + }) + } + + try { + const createdScreen = await createScreenDb(number) + + res.status(201).json({ screen: createdScreen }) + } catch (e) { + console.error(e) + res.status(500).json({ error: e.message }) + } +} + +module.exports = { + createScreen +} \ No newline at end of file diff --git a/src/domains/customer.js b/src/domains/customer.js index c7f315fd..83000518 100644 --- a/src/domains/customer.js +++ b/src/domains/customer.js @@ -1,9 +1,5 @@ const prisma = require('../utils/prisma') -/** - * This will create a Customer AND create a new Contact, then automatically relate them with each other - * @tutorial https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record - */ const createCustomerDb = async (name, phone, email) => await prisma.customer.create({ data: { name, @@ -14,13 +10,30 @@ const createCustomerDb = async (name, phone, email) => await prisma.customer.cre } } }, - // We add an `include` outside of the `data` object to make sure the new contact is returned in the result - // This is like doing RETURNING in SQL + include: { + contact: true + } +}) + +const updateCustomerDb = async (id, name, phone, email) => await prisma.customer.update({ + where: { + id: id + }, + data: { + name, + contact: { + update: { + phone, + email + } + } + }, include: { contact: true } }) module.exports = { - createCustomerDb + createCustomerDb, + updateCustomerDb } diff --git a/src/domains/movies.js b/src/domains/movies.js new file mode 100644 index 00000000..aff3578d --- /dev/null +++ b/src/domains/movies.js @@ -0,0 +1,46 @@ +const prisma = require('../utils/prisma') + +const getMoviesDb = async () => await prisma.movie.findMany({ + include: { + screenings: true + } +}) + +const getMovieByIdDb = async (id) => await prisma.movie.findUnique({ + where: { + id: id + }, + include: { + screenings: true + } +}) + +const createMovieDb = async (title, runtimeMins) => await prisma.movie.create({ + data: { + title, + runtimeMins, + }, + include: { + screenings: true + } +}) + +const updateMovieDb = async (id, title, runtimeMins) => await prisma.movie.update({ + where: { + id: id + }, + data: { + title, + runtimeMins + }, + include: { + screenings: true + } +}) + +module.exports = { + getMoviesDb, + getMovieByIdDb, + createMovieDb, + updateMovieDb +} \ No newline at end of file diff --git a/src/domains/screens.js b/src/domains/screens.js new file mode 100644 index 00000000..835e8de0 --- /dev/null +++ b/src/domains/screens.js @@ -0,0 +1,11 @@ +const prisma = require('../utils/prisma') + +const createScreenDb = async (number) => await prisma.screen.create({ + data: { + number, + } +}) + +module.exports = { + createScreenDb +} \ No newline at end of file diff --git a/src/routers/customer.js b/src/routers/customer.js index f14a87fc..cc1cffcd 100644 --- a/src/routers/customer.js +++ b/src/routers/customer.js @@ -1,13 +1,12 @@ const express = require("express"); +const router = express.Router(); + const { - createCustomer + createCustomer, + updateCustomer } = require('../controllers/customer'); -const router = express.Router(); - -// In index.js, we told express that the /customer route should use this router file -// The below /register route extends that, so the end result will be a URL -// that looks like http://localhost:4040/customer/register router.post("/register", createCustomer); +router.put("/:id", updateCustomer); module.exports = router; diff --git a/src/routers/movies.js b/src/routers/movies.js new file mode 100644 index 00000000..7e27fc77 --- /dev/null +++ b/src/routers/movies.js @@ -0,0 +1,16 @@ +const express = require("express"); +const router = express.Router(); + +const { + getMovies, + getMovieById, + createMovie, + updateMovie +} = require('../controllers/movies'); + +router.get("/", getMovies); +router.get("/:id", getMovieById); +router.post("/", createMovie); +router.put("/:id", updateMovie); + +module.exports = router; diff --git a/src/routers/screens.js b/src/routers/screens.js new file mode 100644 index 00000000..ef3cd3b7 --- /dev/null +++ b/src/routers/screens.js @@ -0,0 +1,10 @@ +const express = require("express"); +const router = express.Router(); + +const { + createScreen, +} = require('../controllers/screens'); + +router.post('/', createScreen); + +module.exports = router; diff --git a/src/server.js b/src/server.js index 93d47a16..a1bad80c 100644 --- a/src/server.js +++ b/src/server.js @@ -15,7 +15,13 @@ app.use(express.urlencoded({ extended: true })); // Tell express to use your routers here const customerRouter = require('./routers/customer'); +const movieRouter = require('./routers/movies'); +const screenRouter = require('./routers/screens'); + app.use('/customers', customerRouter); +app.use('/movies', movieRouter); +app.use('/screens', screenRouter); + module.exports = app