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

[Finishes #187354261] buyer wish list for products #51

Merged
merged 1 commit into from
May 10, 2024
Merged
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
1 change: 1 addition & 0 deletions src/controllers/productsController.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Request, Response } from 'express';
import uploadImage from '../helpers/claudinary';
Expand Down
111 changes: 111 additions & 0 deletions src/controllers/wishlistController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { Request, Response } from 'express';
import Wishlist from '../database/models/wishlist';
import { Product } from '../database/models/Product';
import { Size } from '../database/models/Size';
import { sendInternalErrorResponse } from '../validations';
import User from '../database/models/user';

export const addToWishlist = async (req: Request, res: Response) => {
try {
const { id } = req.params;
const user = req.user as User;

const itemExist = await Wishlist.findOne({
where: {
userId: user.id,
sizeId: id,
},
});
if (itemExist) {
return res.status(400).json({
ok: false,
message: 'Product already added to wishlist',
});
}
await Wishlist.create({
userId: user.id,
sizeId: id,
});

return res.status(201).json({
ok: true,
message: 'Product added to wishlist successfully',
});
} catch (err) {
return sendInternalErrorResponse(res, err);
}
};
export const getWishlist = async (req: Request, res: Response) => {
try {
const userId = (req.user as User).id;

const wishlistItems = await Wishlist.findAll({
where: {
userId,
},
include: {
model: Size,
attributes: ['productId', 'price', 'quantity', 'id'],
},
});
const productIds = wishlistItems.map((item: any) => item.Size.productId);

const wishlistproducts = await Product.findAll({
where: { id: productIds },
});

const combinedResponse = wishlistItems.map((wishlistItem: any) => {
const matchingProduct = wishlistproducts.find((product: any) => product.id === wishlistItem.Size.productId);
return {
id: wishlistItem.dataValues.id,
name: matchingProduct?.dataValues.name,
image: matchingProduct?.dataValues.images[0],
productId: wishlistItem.dataValues.Size.dataValues.id,
price: wishlistItem.dataValues.Size.dataValues.price,
};
});

return res.status(200).json({
hozayves marked this conversation as resolved.
Show resolved Hide resolved
ok: true,
message: 'Wishlist fetched successfully',
data: combinedResponse,
});
} catch (err) {
return sendInternalErrorResponse(res, err);
}
};

export const clearWishList = async (req: Request, res: Response) => {
try {
const userId = (req.user as User).id;

const rowsAffected = await Wishlist.destroy({ where: { userId } });

if (rowsAffected > 0) {
return res.status(200).json({
ok: true,
message: 'Wishlist cleared successfully',
});
} else {
return res.status(404).json({
ok: false,
message: 'No wishlist items found for deletion',
});
}
} catch (err) {
return sendInternalErrorResponse(res, err);
}
};
export const deleteWishlistItem = async (req: Request, res: Response) => {
const user = req.user as User;
const { id } = req.params;
try {
await Wishlist.destroy({ where: { userId: user.id, id } });
return res.status(200).json({
ok: true,
message: 'Wishlist item deleted successfully',
});
} catch (err) {
return sendInternalErrorResponse(res, err);
}
};
47 changes: 47 additions & 0 deletions src/database/migrations/20240508175113-create-wishlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
// const sequelize=require('sequelize');
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Wishlists', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
unique: true,
},
sizeId: {
type: Sequelize.UUID,
allowNull: false,
foreignKey: true,
references: {
model: 'sizes',
key: 'id',
},
},
userId: {
type: Sequelize.UUID,
allowNull: false,
foreignKey: true,
references: {
model: 'Users',
key: 'id',
},
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('NOW()'),
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},
});
},
async down(queryInterface) {
await queryInterface.dropTable('Wishlists');
},
};
1 change: 0 additions & 1 deletion src/database/models/Category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export class Category extends Model<CategoryAttributes, CategoryCreationAttribut
public id!: number;
public name!: string;
public description!: string;
public sizes!: string[];
}

Category.init(
Expand Down
48 changes: 48 additions & 0 deletions src/database/models/wishlist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Model, DataTypes } from 'sequelize';
import sequelize from '.';
import { Size } from './Size';

interface WishlistAttributes {
id: string;
userId: string;
sizeId: string;
}

interface WishlistCreationAttributes extends Omit<WishlistAttributes, 'id'> {
id?: string;
}

class Wishlist extends Model<WishlistAttributes, WishlistCreationAttributes> implements WishlistAttributes {
public id!: string;
public userId!: string;
public sizeId!: string;

public static associate(models: { Size: typeof Size }): void {
Wishlist.belongsTo(models.Size, {
foreignKey: 'sizeId',
as: 'size',
});
}
}

Wishlist.init(
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
userId: DataTypes.UUID,
sizeId: DataTypes.UUID,
},
{
sequelize,
modelName: 'Wishlist',
tableName: 'Wishlists', // Corrected table name to match convention
timestamps: true,
}
);

Wishlist.belongsTo(Size, { foreignKey: 'sizeId' });
Size.hasMany(Wishlist, { foreignKey: 'sizeId' });
export default Wishlist;
138 changes: 138 additions & 0 deletions src/docs/wishlist.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
tags:
- name: Wishlist
description: Buyer Wishlist

paths:
/api/wishlist/add-wishlist/{id}:
post:
summary: Add product to wishlist
tags:
- Wishlist
security:
- bearerAuth: []
parameters:
- in: path
name: id
require: true
type: string
responses:
201:
description: Product added to wishlist successfully
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
data:
$ref: '#/definitions/WishlistItem'
400:
description: Product not found
schema:
$ref: '#/definitions/Error'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/Error'

/api/wishlist/get-wishlist:
get:
summary: Get user's wishlist
tags:
- Wishlist
security:
- bearerAuth: []
responses:
200:
description: Wishlist fetched successfully
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
wishlistItems:
type: array
items:
$ref: '#/definitions/WishlistItem'
500:
description: Internal Server Error
schema:
$ref: '#/definitions/Error'

/api/wishlist:
delete:
summary: Clear user's wishlist
tags:
- Wishlist
security:
- bearerAuth: []
responses:
200:
description: Wishlist cleared successfully
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
500:
description: Internal Server Error
schema:
$ref: '#/definitions/Error'

/api/wishlist/{id}:
delete:
summary: Delete a product from wishlist
tags:
- Wishlist
security:
- bearerAuth: []
parameters:
- in: path
name: id
description: wishList item id
required: true
type: string
responses:
200:
description: Wishlist item deleted successfully
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
500:
description: Internal Server Error
schema:
$ref: '#/definitions/Error'

definitions:
WishlistItem:
type: object
properties:
id:
type: string
userId:
type: string
productId:
type: string
images:
type: array
items:
type: string
name:
type: string
price:
type: number

Error:
type: object
properties:
message:
type: string
2 changes: 2 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import authRoute from './authRoute';
import roleRoute from './roleRoute';
import { productRouter } from './productRoutes';
import { categoryRouter } from './categoryRouter';
import wishlistRoute from './wishlistRoute';

const router = Router();

Expand All @@ -13,4 +14,5 @@ router.use('/auth', authRoute);
router.use('/roles', roleRoute);
router.use('/products', productRouter);
router.use('/category', categoryRouter);
router.use('/wishlist', wishlistRoute);
export default router;
12 changes: 12 additions & 0 deletions src/routes/wishlistRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Router } from 'express';
import { addToWishlist, getWishlist, clearWishList, deleteWishlistItem } from '../controllers/wishlistController';
import { isAuthenticated, checkUserRoles } from '../middlewares/authMiddlewares';

const router = Router();

router.post('/add-wishlist/:id', isAuthenticated, checkUserRoles('buyer'), addToWishlist);
router.get('/get-wishlist', isAuthenticated, checkUserRoles('buyer'), getWishlist);
router.delete('/:id', isAuthenticated, checkUserRoles('buyer'), deleteWishlistItem);
router.delete('/', isAuthenticated, checkUserRoles('buyer'), clearWishList);

export default router;
Loading