From f5d1f3eadd405bd8244e31c2ff87a3050031c599 Mon Sep 17 00:00:00 2001 From: Kyle Belanger Date: Wed, 5 Mar 2025 16:11:52 -0500 Subject: [PATCH] add Controllers --- backend/src/controllers/authController.js | 85 ++++++++++++ .../src/controllers/collectionController.js | 121 ++++++++++++++++ backend/src/controllers/ratingController.js | 123 +++++++++++++++++ backend/src/controllers/whiskeyController.js | 130 ++++++++++++++++++ 4 files changed, 459 insertions(+) create mode 100644 backend/src/controllers/authController.js create mode 100644 backend/src/controllers/collectionController.js create mode 100644 backend/src/controllers/ratingController.js create mode 100644 backend/src/controllers/whiskeyController.js diff --git a/backend/src/controllers/authController.js b/backend/src/controllers/authController.js new file mode 100644 index 0000000..febdb27 --- /dev/null +++ b/backend/src/controllers/authController.js @@ -0,0 +1,85 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models/User'); +const { Op } = require('sequelize'); + +exports.register = async (req, res) => { + try { + const { username, email, password } = req.body; + + // Check is user exits + const existingUser = await User.findOne({ + where: { + [Op.or]: [{ email }, { username }] + } + }); + + if (existingUser) { + return res.status(400).json({ message: 'Username or email already exists'}); + } + + // Create a new user + const user = await User.create({ + username, + email, + password + }); + + // Generate JWT + const token = jwt.sign( + { id: user.id, username: user.username}, + process.env.JWT_SECRET, + { expiresIn: '24h'} + ); + + res.status(201).json({ + message: 'User registered successfully', + token, + user: { + id: user.id, + username: user.username, + email: user.email + } + }); + } catch (error) { + console.error('Registration error:', error); + res.status(500).json({ message: 'Server error during registration'}); + } +}; + +exports.login = async (req, res) => { + try { + const { email, password } = req.body; + + // Find User + const user = await User.findOne({ where: { email }}); + if (!user) { + return res.status(404).json({message: "User not found"}); + } + + // Validate Password + const isPasswordValid = await user.validatePassword(password); + if (!isPasswordValid) { + return res.status(404).json({message: "Invalid password"}); + } + + // Generate JWT + const token = jwt.sign( + { id: user.id, username: user.username}, + process.env.JWT_SECRET, + { expiresIn: '24h'} + ); + + res.status(200).json({ + message: 'Login successful', + token, + user: { + id: user.id, + username: user.username, + email: user.email + } + }); + } catch (error) { + console.error('Login Error:', error); + res.status(500).json({ message: 'Server error during login'}); + } +} \ No newline at end of file diff --git a/backend/src/controllers/collectionController.js b/backend/src/controllers/collectionController.js new file mode 100644 index 0000000..b764eba --- /dev/null +++ b/backend/src/controllers/collectionController.js @@ -0,0 +1,121 @@ +const { Collection, Whiskey } = require('../models/Whiskey'); + +// Get user's collection +exports.getUserCollection = async (req, res) => { + try { + const userId = req.user.id; + + const collection = await Collection.findAll({ + where: { UserId: userId }, + include: [Whiskey] + }); + + res.status(200).json(collection); + } catch (error) { + console.error('Error fetching collection:', error); + res.status(500).json({ message: 'Error fetching collection' }); + } +}; + +// Add whiskey to collection +exports.addToCollection = async (req, res) => { + try { + const userId = req.user.id; + const { whiskeyId, purchaseDate, purchasePrice, notes, bottleStatus } = req.body; + + // Check if whiskey exists + const whiskey = await Whiskey.findByPk(whiskeyId); + if (!whiskey) { + return res.status(404).json({ message: 'Whiskey not found' }); + } + + // Check if already in collection + const existingEntry = await Collection.findOne({ + where: { + UserId: userId, + WhiskeyId: whiskeyId + } + }); + + if (existingEntry) { + return res.status(400).json({ message: 'Whiskey already in collection' }); + } + + // Add to collection + const collectionEntry = await Collection.create({ + UserId: userId, + WhiskeyId: whiskeyId, + purchaseDate, + purchasePrice, + notes, + bottleStatus + }); + + // Get the collection entry with whiskey details + const result = await Collection.findByPk(collectionEntry.id, { + include: [Whiskey] + }); + + res.status(201).json(result); + } catch (error) { + console.error('Error adding to collection:', error); + res.status(500).json({ message: 'Error adding to collection' }); + } +}; + +// Update collection entry +exports.updateCollectionEntry = async (req, res) => { + try { + const userId = req.user.id; + const { id } = req.params; + + const entry = await Collection.findOne({ + where: { + id, + UserId: userId + } + }); + + if (!entry) { + return res.status(404).json({ message: 'Collection entry not found' }); + } + + await entry.update(req.body); + + // Get updated entry with whiskey details + const updatedEntry = await Collection.findByPk(entry.id, { + include: [Whiskey] + }); + + res.status(200).json(updatedEntry); + } catch (error) { + console.error('Error updating collection entry:', error); + res.status(500).json({ message: 'Error updating collection entry' }); + } +}; + +// Remove from collection +exports.removeFromCollection = async (req, res) => { + try { + const userId = req.user.id; + const { id } = req.params; + + const entry = await Collection.findOne({ + where: { + id, + UserId: userId + } + }); + + if (!entry) { + return res.status(404).json({ message: 'Collection entry not found' }); + } + + await entry.destroy(); + + res.status(200).json({ message: 'Removed from collection successfully' }); + } catch (error) { + console.error('Error removing from collection:', error); + res.status(500).json({ message: 'Error removing from collection' }); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/ratingController.js b/backend/src/controllers/ratingController.js new file mode 100644 index 0000000..b0c007c --- /dev/null +++ b/backend/src/controllers/ratingController.js @@ -0,0 +1,123 @@ +const { Rating, Whiskey, User } = require('../models/Whiskey'); + +// Get all ratings for a whiskey +exports.getWhiskeyRatings = async (req, res) => { + try { + const { whiskeyId } = req.params; + + const ratings = await Rating.findAll({ + where: { WhiskeyId: whiskeyId }, + include: [ + { + model: User, + attributes: ['id', 'username'] + } + ] + }); + + res.status(200).json(ratings); + } catch (error) { + console.error('Error fetching ratings:', error); + res.status(500).json({ message: 'Error fetching ratings' }); + } +}; + +// Get user's ratings +exports.getUserRatings = async (req, res) => { + try { + const userId = req.user.id; + + const ratings = await Rating.findAll({ + where: { UserId: userId }, + include: [Whiskey] + }); + + res.status(200).json(ratings); + } catch (error) { + console.error('Error fetching user ratings:', error); + res.status(500).json({ message: 'Error fetching user ratings' }); + } +}; + +// Add or update rating +exports.rateWhiskey = async (req, res) => { + try { + const userId = req.user.id; + const { whiskeyId } = req.params; + const { score, notes, nose, taste, finish } = req.body; + + // Check if whiskey exists + const whiskey = await Whiskey.findByPk(whiskeyId); + if (!whiskey) { + return res.status(404).json({ message: 'Whiskey not found' }); + } + + // Check if user already rated this whiskey + const existingRating = await Rating.findOne({ + where: { + UserId: userId, + WhiskeyId: whiskeyId + } + }); + + let rating; + + if (existingRating) { + // Update existing rating + rating = await existingRating.update({ + score, + notes, + nose, + taste, + finish + }); + } else { + // Create new rating + rating = await Rating.create({ + UserId: userId, + WhiskeyId: whiskeyId, + score, + notes, + nose, + taste, + finish + }); + } + + // Get the rating with whiskey details + const result = await Rating.findByPk(rating.id, { + include: [Whiskey] + }); + + res.status(200).json(result); + } catch (error) { + console.error('Error rating whiskey:', error); + res.status(500).json({ message: 'Error rating whiskey' }); + } +}; + +// Delete rating +exports.deleteRating = async (req, res) => { + try { + const userId = req.user.id; + const { id } = req.params; + + const rating = await Rating.findOne({ + where: { + id, + UserId: userId + } + }); + + if (!rating) { + return res.status(404).json({ message: 'Rating not found' }); + } + + await rating.destroy(); + + res.status(200).json({ message: 'Rating deleted successfully' }); + } catch (error) { + console.error('Error deleting rating:', error); + res.status(500).json({ message: 'Error deleting rating' }); + } +}; \ No newline at end of file diff --git a/backend/src/controllers/whiskeyController.js b/backend/src/controllers/whiskeyController.js new file mode 100644 index 0000000..fd5951c --- /dev/null +++ b/backend/src/controllers/whiskeyController.js @@ -0,0 +1,130 @@ +const { Whiskey } = require('../models/Whiskey'); +const { Op } = require('sequelize'); + +// Get all whiskies +exports.getAllWhiskies = async (req, res) => { + try { + const whiskies = await Whiskey.findAll(); + res.status(200).json(whiskies); + } catch (error) { + console.error('Error fetching whiskies:', error); + res.status(500).json({ message: 'Error fetching whiskies' }); + } +}; + +// Get whiskey by ID +exports.getWhiskeyById = async (req, res) => { + try { + const whiskey = await Whiskey.findByPk(req.params.id); + if (!whiskey) { + return res.status(404).json({ message: 'Whiskey not found' }); + } + res.status(200).json(whiskey); + } catch (error) { + console.error('Error fetching whiskey:', error); + res.status(500).json({ message: 'Error fetching whiskey' }); + } +}; + +// Create new whiskey +exports.createWhiskey = async (req, res) => { + try { + const { + name, + distillery, + type, + country, + region, + age, + abv, + price, + description, + imageUrl + } = req.body; + + const whiskey = await Whiskey.create({ + name, + distillery, + type, + country, + region, + age, + abv, + price, + description, + imageUrl + }); + + res.status(201).json(whiskey); + } catch (error) { + console.error('Error creating whiskey:', error); + res.status(500).json({ message: 'Error creating whiskey' }); + } +}; + +// Update whiskey +exports.updateWhiskey = async (req, res) => { + try { + const whiskey = await Whiskey.findByPk(req.params.id); + if (!whiskey) { + return res.status(404).json({ message: 'Whiskey not found' }); + } + + await whiskey.update(req.body); + res.status(200).json(whiskey); + } catch (error) { + console.error('Error updating whiskey:', error); + res.status(500).json({ message: 'Error updating whiskey' }); + } +}; + +// Delete whiskey +exports.deleteWhiskey = async (req, res) => { + try { + const whiskey = await Whiskey.findByPk(req.params.id); + if (!whiskey) { + return res.status(404).json({ message: 'Whiskey not found' }); + } + + await whiskey.destroy(); + res.status(200).json({ message: 'Whiskey deleted successfully' }); + } catch (error) { + console.error('Error deleting whiskey:', error); + res.status(500).json({ message: 'Error deleting whiskey' }); + } +}; + +// Search whiskies +exports.searchWhiskies = async (req, res) => { + try { + const { query, type, country } = req.query; + + let whereClause = {}; + + if (query) { + whereClause = { + [Op.or]: [ + { name: { [Op.iLike]: `%${query}%` } }, + { distillery: { [Op.iLike]: `%${query}%` } } + ] + }; + } + + if (type) { + whereClause.type = type; + } + + if (country) { + whereClause.country = country; + } + + const whiskies = await Whiskey.findAll({ + where: whereClause + }); + + res.status(200).json(whiskies); + } catch (error) { + console.error('Error searching whiskies:', error); + res.status(500).json({ message: 'Error searching whiskies' }); + } +}; \ No newline at end of file