Skip to content

Commit

Permalink
complete api
Browse files Browse the repository at this point in the history
  • Loading branch information
Dagwan committed Nov 1, 2024
1 parent 6e47e75 commit 5aee1bd
Show file tree
Hide file tree
Showing 287 changed files with 25,273 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"env": {
"es2021": true,
"node": true,
"jest": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"rules": {}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"jsxBracketSameLine": true
}
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node server.js
106 changes: 106 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Handcrafted Haven API

The Handcrafted Haven API is a RESTful web service designed for managing user accounts, products, orders, and payments in a marketplace dedicated to handcrafted items. Built with Node.js and Express.js, this API connects artisans with customers, enabling artisans to showcase and sell their unique products while providing essential functionalities like user registration, product listing, cart management, and payment processing. The API ensures secure interactions through JWT authentication and includes comprehensive endpoints for efficient CRUD operations, enhancing the overall user experience in the marketplace.

## Overview

Handcrafted Haven aims to connect talented artisans with customers by providing a platform to showcase and sell unique handcrafted products. The API supports essential functionalities such as product listing, user registration, cart management, and payment processing.

## API Endpoints

### User Endpoints

- **POST /api/v1/users/register**
- Registers a new user account.
- Required fields: `username`, `password`, and `email`.
- Returns a confirmation of successful registration or an error message if registration fails.

- **POST /api/v1/users/login**
- Authenticates a user and returns a JWT token for authorized access.
- Required fields: `username` and `password`.

### Product Endpoints

- **GET /api/v1/products**
- Retrieves a list of all products available in the marketplace.
- Optional query parameters can filter products by category, price range, or artisan.

- **POST /api/v1/products**
- Adds a new product to the marketplace.
- Required fields: `name`, `description`, `price`, and `artisan`.
- Only authorized users (artisans) can create products.

- **PUT /api/v1/products/:id**
- Updates the details of a specific product.
- Requires a valid product `id` and the fields to update (e.g., `name`, `price`).

- **DELETE /api/v1/products/:id**
- Deletes a specified product from the marketplace.
- Requires a valid product `id` and authorization.

### Order Endpoints

- **GET /api/v1/orders**
- Retrieves a list of all orders placed by users.
- Requires authorization.

- **POST /api/v1/orders**
- Places a new order for one or more products.
- Required fields: `userId`, `productIds`, and `quantity`.

- **PUT /api/v1/orders/:id**
- Updates an existing order's details.
- Requires a valid order `id` and the fields to update (e.g., `status`, `quantity`).

- **DELETE /api/v1/orders/:id**
- Cancels an existing order.
- Requires a valid order `id`.

### Payment Endpoints

- **GET /api/v1/payments**
- Retrieves all payment transactions.
- Requires authorization.

- **POST /api/v1/payments**
- Processes a payment for an order.
- Required fields: `orderId`, `amount`, and `paymentMethod`.

### Cart Endpoints

- **GET /api/v1/cart**
- Retrieves the current user's shopping cart items.
- Requires authorization.

- **POST /api/v1/cart**
- Adds an item to the user's shopping cart.
- Required fields: `productId` and `quantity`.

- **DELETE /api/v1/cart/:itemId**
- Removes an item from the user's shopping cart.
- Requires the `itemId` of the cart item to be removed.

## Authentication

The API uses JWT tokens for securing endpoints. After a successful login, include the token in the `Authorization` header of subsequent requests to access protected endpoints.

## Error Handling

The API returns error messages with appropriate HTTP status codes:
- `400 Bad Request` for invalid inputs.
- `401 Unauthorized` for missing or invalid authentication tokens.
- `404 Not Found` for non-existent resources.
- `500 Internal Server Error` for unexpected server issues.

## Setup

To run this project locally:
1. Clone the repository.
2. Install dependencies:
```bash
npm install


### License

This project is licensed under the MIT License - see the [LICENSE](/docs/LICENSE) file for details.
147 changes: 147 additions & 0 deletions controllers/carttemController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
const mongodb = require('../db/db');
const { validationResult } = require('express-validator');
const ObjectId = require('mongodb').ObjectId;

// Create a new cart item
const createCartItem = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}

const { cartId, productId, quantity } = req.body;

// Create the new cart item entry object
const cartItemEntry = {
cartId: new ObjectId(cartId),
productId: new ObjectId(productId),
quantity,
createdAt: new Date(),
updatedAt: new Date(),
};

// Insert the new cart item entry into the 'cartitems' collection
const response = await mongodb.getDb().db().collection('cartitems').insertOne(cartItemEntry);

if (response.acknowledged) {
res.status(201).json({ success: 'Cart item created successfully', cartItemId: response.insertedId });
} else {
res.status(500).json({ error: 'Error occurred while creating the cart item.' });
}
} catch (error) {
console.error('Error creating a cart item:', error);
res.status(500).json({ error: 'An error occurred while creating the cart item.' });
}
};

// Get all cart items for a specific cart
const getCartItemsForCart = async (req, res) => {
try {
const cartId = req.params.cartId;

if (!ObjectId.isValid(cartId)) {
return res.status(400).json({ error: 'Invalid cart ID format.' });
}

const result = await mongodb.getDb().db().collection('cartitems').find({ cartId: new ObjectId(cartId) });
const cartItems = await result.toArray();

res.setHeader('Content-Type', 'application/json');
res.status(200).json(cartItems);
} catch (error) {
console.error('Error fetching cart items for cart:', error);
res.status(500).json({ error: 'An error occurred while fetching cart items.' });
}
};

// Get a single cart item by ID
const getSingleCartItem = async (req, res) => {
try {
const cartItemId = req.params.id;

if (!ObjectId.isValid(cartItemId)) {
return res.status(400).json({ error: 'Invalid cart item ID format.' });
}

const cartItemEntry = await mongodb.getDb().db().collection('cartitems').findOne({ _id: new ObjectId(cartItemId) });

if (!cartItemEntry) {
return res.status(404).json({ error: 'Cart item not found.' });
}

res.status(200).json(cartItemEntry);
} catch (error) {
console.error('Error fetching a single cart item by ID:', error);
res.status(500).json({ error: 'An error occurred while fetching the cart item.' });
}
};

// Update a cart item by ID
const updateCartItem = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}

const cartItemId = req.params.id;
const { cartId, productId, quantity } = req.body;

if (!ObjectId.isValid(cartItemId)) {
return res.status(400).json({ error: 'Invalid cart item ID format.' });
}

// Update the cart item entry in the database
const result = await mongodb.getDb().db().collection('cartitems').updateOne(
{ _id: new ObjectId(cartItemId) },
{
$set: {
cartId: new ObjectId(cartId),
productId: new ObjectId(productId),
quantity,
updatedAt: new Date(),
},
}
);

if (result.modifiedCount === 0) {
return res.status(404).json({ error: 'Cart item not modified.' });
}

res.status(200).json({ success: 'Cart item updated successfully.' });
} catch (error) {
console.error('Error updating cart item:', error);
res.status(500).json({ error: 'An error occurred while updating the cart item.' });
}
};

// Delete a cart item by ID
const deleteCartItem = async (req, res) => {
try {
const cartItemId = req.params.id;

if (!ObjectId.isValid(cartItemId)) {
return res.status(400).json({ error: 'Invalid cart item ID format.' });
}

const result = await mongodb.getDb().db().collection('cartitems').deleteOne({ _id: new ObjectId(cartItemId) });

if (result.deletedCount === 0) {
return res.status(404).json({ error: 'Cart item not found.' });
}

res.status(200).json({ success: 'Cart item deleted successfully.' });
} catch (error) {
console.error('Error deleting cart item:', error);
res.status(500).json({ error: 'An error occurred while deleting the cart item.' });
}
};

module.exports = {
createCartItem,
getCartItemsForCart,
getSingleCartItem,
updateCartItem,
deleteCartItem,
};
Loading

0 comments on commit 5aee1bd

Please sign in to comment.