Skip to content

Commit

Permalink
Fixed slow ingredient search
Browse files Browse the repository at this point in the history
  • Loading branch information
orionsoti committed Oct 5, 2023
1 parent 8855fb1 commit d089f6d
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 90 deletions.
15 changes: 7 additions & 8 deletions assets/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -179,26 +179,25 @@ button:active,
background-color: #f2f2f2;
}


/* RECIPE CARD STYLING */
#search-results {
#search-results, #saved-recipe-container, #andrews-recipe-container, #featured-recipe-container {
/*width : 100%;*/
display: grid;
grid-template-columns: repeat(auto-fill, minmax(auto, 1fr));
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-template-rows: masonry;
gap: 10px;
align-items: start;
/*align-items: start;*/
}

.recipe-card {
display: flex;
flex-direction: column;
/*display: flex;
flex-direction: column; */
border-radius: 20px;
padding: 10px;
margin: 10px;
background-color: white;
box-shadow: 0 0 10px lightgrey;
width: calc(33.333% - 20px);
box-sizing: border-box;
max-width: 400px;
}

.recipe-card button {
Expand Down
82 changes: 56 additions & 26 deletions assets/scripts/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,19 @@ function searchRecipes() {

const jsonRecipes = SearchRecipes(ingredients);
const recipes = JSON.parse(jsonRecipes);

const recipeIds = recipes.map(r => r.recipeId);
// Fetch ingredients for all these recipes
const jsonIngredients = GetIngredientsForRecipes(recipeIds);
const allIngredients = JSON.parse(jsonIngredients);

console.log("Recipes:", recipes);
document.getElementById('search-results').innerHTML = "";

document.getElementById('search-results').innerHTML = "";
for (let recipe of recipes) {
displayCard(recipe, "search-results");
const recipeIngredients = allIngredients[recipe.recipeId];
displayCard(recipe, "search-results", recipeIngredients);
}
} catch (error) {
console.error("Error fetching recipes:", error);
Expand All @@ -83,20 +90,22 @@ function createStars(rating) {
return starsWrapper;
}

/*
var msnry;
// Wait for the content to load
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('DOMContentLoaded', function () {
// Initialize masonry
var grid = document.querySelector('#search-results');
msnry = new Masonry( grid, {
// options
itemSelector: '.recipe-card',
columnWidth: '.recipe-card',
percentPosition: true
msnry = new Masonry(grid, {
// options
itemSelector: '.recipe-card',
columnWidth: '.recipe-card',
percentPosition: true
});
});
*/

function displayCard(recipe, location) {
function displayCard(recipe, location, ingredientsArray) {
const searchResults = document.getElementById(location);
// Create a div for the card
const card = document.createElement('div');
Expand Down Expand Up @@ -150,7 +159,6 @@ function displayCard(recipe, location) {
ingredientsHeader.textContent = 'Ingredients';
ingredientsDiv.appendChild(ingredientsHeader);
const ingredientsList = document.createElement('ul');
const ingredientsArray = JSON.parse(GetIngredientsByRecipe(recipe.recipeId));
for (const ingredient of ingredientsArray) {
const ingredientItem = document.createElement('li');
ingredientItem.textContent = ingredient.Name;
Expand Down Expand Up @@ -180,7 +188,7 @@ function displayCard(recipe, location) {
// Add favorite button to the card
const favourite = document.createElement("button");
favourite.className = ("favourite-icon");
favourite.innerHTML = "♥";
favourite.innerHTML = "♥";
favourite.setAttribute("aria-label", "Add to favourites");
favourite.onclick = function () {
addToSaved(recipe.recipeId);
Expand Down Expand Up @@ -252,18 +260,19 @@ function displayCard(recipe, location) {
popupDiv.appendChild(buttonAddMeal);

popupContainer.appendChild(popupDiv);

recipeInfo.appendChild(favourite);
recipeInfo.appendChild(addSymbol);
recipeInfo.appendChild(popupContainer);

card.appendChild(recipeInfo);
searchResults.appendChild(card);

if (msnry) {
msnry.appended(card);
msnry.layout();
}
//if (msnry) {
// msnry.appended(card);
// msnry.layout();
//}

}


Expand All @@ -276,45 +285,59 @@ function addToSaved(recipeId) {
let isSaved = false;

for (let i = 0; i < savedRecipes.length; i++) {
if(savedRecipes[i] == recipeId){
isSaved=true;
if (savedRecipes[i] == recipeId) {
isSaved = true;
}
}
if(!isSaved){
if (!isSaved) {
savedRecipes.push(recipeId);
console.log("saved recipe(s):\n")
SaveRecipe(recipeId);
}else{
} else {
console.log("already saved\n")
}
}

//function which retrieves saved recipes from c
function getSaved(){
function getSaved() {
try {
const jsonRecipes = GetSaved();
const recipes = JSON.parse(jsonRecipes);

const recipeIds = recipes.map(r => r.recipeId);
// Fetch ingredients for all these recipes
const jsonIngredients = GetIngredientsForRecipes(recipeIds);
const allIngredients = JSON.parse(jsonIngredients);

console.log("Recipes:", recipes);
document.getElementById('saved-recipe-container').innerHTML = "";

for (let recipe of recipes) {
displayCard(recipe, 'saved-recipe-container');
const recipeIngredients = allIngredients[recipe.recipeId];
displayCard(recipe, 'saved-recipe-container', recipeIngredients);
}
} catch (error) {
console.error("Error fetching recipes:", error);
alert("Failed to fetch recipes. Please try again later.");
}
}

function getAndrews(){
function getAndrews() {
try {
const jsonRecipes = GetAndrews();
const recipes = JSON.parse(jsonRecipes);

const recipeIds = recipes.map(r => r.recipeId);
// Fetch ingredients for all these recipes
const jsonIngredients = GetIngredientsForRecipes(recipeIds);
const allIngredients = JSON.parse(jsonIngredients);

console.log("Recipes:", recipes);
document.getElementById('andrews-recipe-container').innerHTML = "";

for (let recipe of recipes) {
displayCard(recipe, 'andrews-recipe-container');
const recipeIngredients = allIngredients[recipe.recipeId];
displayCard(recipe, 'andrews-recipe-container', recipeIngredients);
}
} catch (error) {
console.error("Error fetching recipes:", error);
Expand All @@ -323,15 +346,22 @@ function getAndrews(){
}


function getFeatured(){
function getFeatured() {
try {
const jsonRecipes = ShowFeatured();
const recipes = JSON.parse(jsonRecipes);

const recipeIds = recipes.map(r => r.recipeId);
// Fetch ingredients for all these recipes
const jsonIngredients = GetIngredientsForRecipes(recipeIds);
const allIngredients = JSON.parse(jsonIngredients);

console.log("Recipes:", recipes);
document.getElementById('featured-recipe-container').innerHTML = "";

for (let recipe of recipes) {
displayCard(recipe, 'featured-recipe-container');
const recipeIngredients = allIngredients[recipe.recipeId];
displayCard(recipe, 'featured-recipe-container', recipeIngredients);
}
} catch (error) {
console.error("Error fetching recipes:", error);
Expand Down Expand Up @@ -359,7 +389,7 @@ function addToPlanner(recipeName, recipeId) {
const selectedMeal = mealOptions.value;
let mealOption = [];
addToJSON(selectedDay, selectedMeal, recipeName, currRecipeId);
mealOption.push(recipeName, currRecipeId, selectedDay, selectedMeal );
mealOption.push(recipeName, currRecipeId, selectedDay, selectedMeal);
mealPlanner.push(mealOption);
closePopup();
}
Expand Down
57 changes: 32 additions & 25 deletions src/MyApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <Ultralight/Ultralight.h>
#include "timer.h"

#define WINDOW_WIDTH 1000
#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800

std::vector<int> savedRecipes;
Expand Down Expand Up @@ -233,37 +233,44 @@ JSValue MyApp::SearchRecipes(const JSObject &thisObject, const JSArgs &args)
return JSValue(jsonRecipes.c_str());
}

JSValue MyApp::GetIngredientsByRecipe(const JSObject &thisObject, const JSArgs &args)
{
std::cout << "GetIngredientsByRecipe called" << std::endl;
JSValue MyApp::GetIngredientsForRecipes(const JSObject &thisObject, const JSArgs &args) {
std::cout << "GetIngredientsForRecipes called" << std::endl;

std::vector<int> recipeIds;
if (args[0].IsArray()) {
JSArray recipeIdArray = args[0].ToArray();
for (size_t i = 0; i < recipeIdArray.length(); i++) {
recipeIds.push_back(recipeIdArray[i].ToInteger());
}
}

int recipeId = args[0].ToInteger();
RecipeDatabase recipeDB;
std::vector<Ingredient> ingredients = recipeDB.getIngredientsByRecipe(recipeId);
std::map<int, std::vector<Ingredient>> ingredientsMap = recipeDB.getIngredientsForRecipes(recipeIds);

std::ostringstream jsonIngredients;

jsonIngredients << "[";

for (const Ingredient &ingredient : ingredients)
{
jsonIngredients << "{";
jsonIngredients << "\"IngredientId\": " << ingredient.getIngredientId() << ", ";
jsonIngredients << "\"Name\": \"" << escapeJsonString(ingredient.getIngredientName()) << "\"";
jsonIngredients << "},";
jsonIngredients << "{";

for (const auto& pair : ingredientsMap) {
int recipeId = pair.first;
const std::vector<Ingredient>& ingredients = pair.second;
jsonIngredients << "\"" << recipeId << "\": [";
for (const Ingredient &ingredient : ingredients) {
jsonIngredients << "{";
jsonIngredients << "\"IngredientId\": " << ingredient.getIngredientId() << ", ";
jsonIngredients << "\"Name\": \"" << escapeJsonString(ingredient.getIngredientName()) << "\"";
jsonIngredients << "},";
}
if (!ingredients.empty()) {
jsonIngredients.seekp(-1, jsonIngredients.cur); // Remove the trailing comma
}
jsonIngredients << "],";
}

if (!ingredients.empty()){
std::string temp = jsonIngredients.str();
temp.pop_back();
jsonIngredients.str("");
jsonIngredients.clear();
jsonIngredients << temp;
if (!ingredientsMap.empty()) {
jsonIngredients.seekp(-1, jsonIngredients.cur); // Remove the trailing comma
}

jsonIngredients << "]";

//std::cout << "jsonIngredients: " << jsonIngredients.str() << std::endl;
jsonIngredients << "}";

return JSValue(jsonIngredients.str().c_str());
}
Expand Down Expand Up @@ -479,7 +486,7 @@ void MyApp::OnDOMReady(ultralight::View *caller,
global["GetSaved"] = BindJSCallbackWithRetval(&MyApp::GetSaved);
global["GetAndrews"] = BindJSCallbackWithRetval(&MyApp::GetAndrews);
global["ShowFeatured"] = BindJSCallbackWithRetval(&MyApp::ShowFeatured);
global["GetIngredientsByRecipe"] = BindJSCallbackWithRetval(&MyApp::GetIngredientsByRecipe);
global["GetIngredientsForRecipes"] = BindJSCallbackWithRetval(&MyApp::GetIngredientsForRecipes);
global["GetReviewsByRecipe"] = BindJSCallbackWithRetval(&MyApp::GetReviewsByRecipe);
}

Expand Down
2 changes: 1 addition & 1 deletion src/MyApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class MyApp : public AppListener,

void SaveOnExit();

JSValue GetIngredientsByRecipe(const JSObject& thisObject, const JSArgs& args);
JSValue GetIngredientsForRecipes(const JSObject &thisObject, const JSArgs &args);

JSValue GetReviewsByRecipe(const JSObject& thisObject, const JSArgs& args);

Expand Down
38 changes: 25 additions & 13 deletions src/recipeDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,28 +224,40 @@ std::vector<Review> RecipeDatabase::getAllReviewsForRecipes(const std::vector<Re
return reviewVector;
}

std::vector<Ingredient> RecipeDatabase::getIngredientsByRecipe(int recipeId){
std::vector<Ingredient> ingredients;
std::map<int, std::vector<Ingredient>> RecipeDatabase::getIngredientsForRecipes(const std::vector<int>& recipeIds) {
std::map<int, std::vector<Ingredient>> ingredientsMap;

std::string query =
"SELECT ingredients.name, ingredients.ingredientId "
if (recipeIds.empty()) {
return ingredientsMap;
}

std::stringstream query;
query <<
"SELECT ingredients.name, ingredients.ingredientId, recipe_ingredients.recipeId "
"FROM recipe_ingredients JOIN ingredients "
"ON recipe_ingredients.ingredientId = ingredients.ingredientId "
"WHERE recipeId = " + std::to_string(recipeId) + ";";
"WHERE recipe_ingredients.recipeId IN (";

for (size_t i = 0; i < recipeIds.size(); ++i) {
query << recipeIds[i];
if (i < recipeIds.size() - 1) {
query << ",";
}
}
query << ");";

try {
auto con = dbConn.getConnection();
std::unique_ptr<sql::Statement> stmt(con->createStatement());
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(query));
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(query.str()));

while (res->next()) {
//std::cout << "DB Ingredient ID: " << res->getInt("ingredientId") << " Name: " << res->getString("name") << std::endl;
ingredients.push_back(
Ingredient(
res->getInt("ingredientId"),
res->getString("name")
)
int recipeId = res->getInt("recipeId");
Ingredient ingredient(
res->getInt("ingredientId"),
res->getString("name")
);
ingredientsMap[recipeId].push_back(ingredient);
}
} catch (sql::SQLException &e) {
std::cout << "# ERR: SQLException in " << __FILE__ << " on line " << __LINE__ << std::endl;
Expand All @@ -254,7 +266,7 @@ std::vector<Ingredient> RecipeDatabase::getIngredientsByRecipe(int recipeId){
std::cout << ", SQLState: " << e.getSQLState() << " )" << std::endl;
}

return ingredients;
return ingredientsMap;
}

std::vector<RecipeImage> RecipeDatabase::getAllRecipeImagesForRecipes(const std::vector<Recipe>& recipes)
Expand Down
Loading

0 comments on commit d089f6d

Please sign in to comment.