Skip to content

Commit

Permalink
Create status codes & specific error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
lenover12 committed Jun 20, 2024
1 parent cee7adb commit 64872e4
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 38 deletions.
18 changes: 14 additions & 4 deletions client/src/pages/Search.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function Search() {
const handleSubmit = async (e) => {
e.preventDefault();
try {
setFoods([])
setLoading(true);
setError(null);
const response = await axios.get(
Expand All @@ -28,12 +29,21 @@ export default function Search() {
withCredentials: true,
}
);
setFoods(response.data.products);
if (response.status === 200) {
setFoods(response.data.products);
}
} catch (error) {
console.error("Error fetching user foods:", error);
// Set appropriate error message
if (error.response && error.response.status === 429) {
setError("Rate limit reached. Please try again later.");
if (error.response) {
if (error.response.status === 401) {
setError("Authorization Error: Please log in again");
} else if (error.response.status === 429) {
setError("Rate limit reached. Please try again later.");
} else if (error.response.status === 400 || error.response.status === 404) {
setError(`Products not found in OpenFoodFacts database.`);
} else {
setError("An unexpected error occurred while fetching products.");
}
} else {
setError("An error occurred while fetching products.");
}
Expand Down
53 changes: 37 additions & 16 deletions server/controllers/products.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,60 @@ async function searchAndDisplayProducts(req, res) {

// Check if the searchTerm is a barcode
const isBarcode = /^\d+$/.test(searchTerm.trim());

let productData;

if (
isBarcode &&
searchTerm.trim().length >= 8 &&
searchTerm.trim().length <= 14
) {
// Retrieve product by barcode
const product = await ProductsModel.displayProductByBarcode(
productData = await ProductsModel.displayProductByBarcode(
searchTerm,
req
);
if (Object.keys(product).length === 0) {
return res.status(404).send("Product not found");
} else if (product.error) {
return res.status(429).json({ error: product.error });
} else {
return res.status(200).json(product);
}
} else {
// Retrieve data by search term
const productsData = await ProductsModel.displayProductsBySearchTerm(
productData = await ProductsModel.displayProductsBySearchTerm(
searchTerm,
req
);
}

if (productsData.error) {
return res.status(429).json({ error: productsData.error });
// Check for specific error messages and handle accordingly
if (productData.error) {
if (productData.error === "Authorization token is missing") {
return res.status(401).json({
error: `${productData.error}`,
products: [],
});
}

return res.status(200).json(productsData);
if (productData.error === "OpenFoodFacts API rate limit reached") {
return res.status(429).json({
error: `${productData.error}. Please try again later.`,
products: [],
});
}
// If no product(s) data returned
if (Object.keys(productData).length === 0) {
return res.status(404).json({
error: `Products not found in OpenFoodFacts database`,
products: [],
});
}
return res.status(400).json({
error: `Products not found in OpenFoodFacts database`,
products: [],
});
}
// Successful response
return res.status(200).json(productData);
} catch (error) {
console.error("Error searching product:", error);
return res.status(500).json({ error: "Internal server error" });
// Generic internal server error handler
return res.status(500).json({
error: "Internal server error. Please try again later.",
products: [],
});
}
}

Expand Down
57 changes: 40 additions & 17 deletions server/models/products.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,19 @@ ProductModel.formatProductData = function (responseProduct) {

ProductModel.displayProductByBarcode = async function (barcode, req) {
try {
// Ensure barcode and request are provided
if (!barcode) {
throw new Error("Barcode is required");
}

if (!req || !req.cookies || !req.cookies.token) {
throw new Error("Authorization token is missing");
}
// Get the user ID from the JWT token in the request cookies
const user = getUserFromToken(req);

if (!user || !user.id) {
throw new Error("Invalid user authentication");
}
// Fetch user-specific foods from the database
const userFoods = await UserModel.getUserFoods(user.id);

Expand All @@ -148,6 +158,9 @@ ProductModel.displayProductByBarcode = async function (barcode, req) {

// Fetch product data from OpenFoodFacts API endpoint
const productData = await this.fetchOFFProductByBarcode(barcode);
if (!productData || Object.keys(productData).length === 0) {
throw new Error("Products not found in OpenFoodFacts database");
}

// Format the product data from the external API
const product = this.formatProductData(productData);
Expand All @@ -174,22 +187,32 @@ ProductModel.displayProductByBarcode = async function (barcode, req) {
],
};
} catch (error) {
if (error.message === "OpenFoodFacts API rate limit reached") {
return {
products: [],
error: "Rate limit reached. Please try again later.",
};
}
console.error(
`Error displaying product by barcode: ${error.response.status} ${error.response.statusText}`
);

console.error("Error displaying product by barcode:", error);
throw new Error(`Error displaying product by barcode: ${error.message}`);
return {
products: [],
error: error,
};
}
};

ProductModel.displayProductsBySearchTerm = async function (searchTerm, req) {
try {
// Ensure barcode and request are provided
if (!searchTerm) {
throw new Error("Search Term is required");
}

if (!req || !req.cookies || !req.cookies.token) {
throw new Error("Authorization token is missing");
}
// Get the user ID from the JWT token in the request cookies
const user = getUserFromToken(req);
if (!user || !user.id) {
throw new Error("Invalid user authentication");
}

// Fetch user-specific foods from the database
const userFoods = await UserModel.getUserFoods(user.id);
Expand All @@ -201,6 +224,9 @@ ProductModel.displayProductsBySearchTerm = async function (searchTerm, req) {

// Fetch products data from OpenFoodFacts API endpoint
const productsData = await this.fetchOFFProductsBySearch(searchTerm);
if (!productsData || productsData.data.count === 0) {
throw new Error("Products not found in OpenFoodFacts database");
}

// Format the productsData to local database standard
productsData.data.products.forEach((productData, index) => {
Expand All @@ -223,15 +249,12 @@ ProductModel.displayProductsBySearchTerm = async function (searchTerm, req) {

return productsData.data;
} catch (error) {
if (error.message === "OpenFoodFacts API rate limit reached") {
return {
products: [],
error: "Rate limit reached. Please try again later.",
};
}

console.error("Error searching product by search term:", error);
throw error;

return {
products: [],
error: error,
};
}
};

Expand Down
6 changes: 5 additions & 1 deletion server/models/users.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ const UsersModel = {
if (!user) {
throw new Error("User not found");
}
return user.foods;
// Ensure foods.products and foods.wholefoods are arrays
return {
products: user.foods.products || [],
wholefoods: user.foods.wholefoods || [],
};
} catch (error) {
throw new Error(`Error retrieving user's foods: ${error.message}`);
}
Expand Down

0 comments on commit 64872e4

Please sign in to comment.