controller.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /*
  2. Switches to a different strand
  3. Input:
  4. name: name of the strand. Must end with "Strand"
  5. */
  6. let changeStrand = (name)=>{
  7. closeSidebar();
  8. for(let strand of document.querySelectorAll(".strand")){
  9. strand.style.display = "none";
  10. }
  11. for(let button of document.querySelectorAll(".menu > button")){
  12. button.classList = "";
  13. button.onclick = ()=>{changeStrand(`${button.id.slice(0, button.id.indexOf("Btn"))}Strand`)};
  14. }
  15. let activeButton = document.querySelector(`#${name.slice(0, name.indexOf("Strand"))}Btn`);
  16. activeButton.classList = "active";
  17. activeButton.onclick = undefined;
  18. document.querySelector(`#${name}`).style.display = "flex";
  19. window[`${name}Obj`].display();
  20. }
  21. /*
  22. Updates all specified item in the merchant's inventory and updates the page
  23. If ingredient doesn't exist, add it
  24. Inputs:
  25. Array of objects
  26. id: id of ingredient
  27. quantityChange: change in quantity (if not removing)
  28. name: name of ingredient (only for new ingredient)
  29. category: category of ingredient (only for new ingredient)
  30. unit: unit of measurement (only for new ingredient)
  31. remove: if true, remove ingredient from inventory
  32. */
  33. let updateInventory = (ingredients, remove = false)=>{
  34. for(let i = 0; i < ingredients.length; i++){
  35. let isNew = true;
  36. for(let j = 0; j < merchant.inventory.length; j++){
  37. if(merchant.inventory[j].ingredient._id === ingredients[i].id){
  38. if(remove){
  39. merchant.inventory.splice(j, 1);
  40. }else{
  41. merchant.inventory[j].quantity += ingredients[i].quantity;
  42. }
  43. isNew = false;
  44. break;
  45. }
  46. }
  47. if(isNew){
  48. merchant.inventory.push({
  49. ingredient: {
  50. _id: ingredients[i].id,
  51. category: ingredients[i].category,
  52. name: ingredients[i].name,
  53. unit: ingredients[i].unit
  54. },
  55. quantity: parseFloat(ingredients[i].quantityChange)
  56. });
  57. }
  58. }
  59. homeStrandObj.drawInventoryCheckCard();
  60. ingredientsStrandObj.populateByProperty("category");
  61. addIngredientsComp.isPopulated = false;
  62. closeSidebar();
  63. }
  64. /*
  65. Updates a recipe in the merchants list of recipes
  66. Can create, edit or remove
  67. Inputs:
  68. recipe: object
  69. _id: id of recipe
  70. name: name of recipe
  71. price: price of recipe
  72. ingredients: list of ingredients
  73. ingredient: id of ingredient
  74. quantity: quantity of ingredient
  75. remove: if true, remove ingredient from inventory
  76. */
  77. let updateRecipes = (recipe, remove = false)=>{
  78. let isNew = true;
  79. let index = 0;
  80. for(let i = 0; i < recipe.ingredients.length; i++){
  81. for(let j = 0; j < merchant.inventory.length; j++){
  82. if(merchant.inventory[j].ingredient._id === recipe.ingredients[i].ingredient){
  83. recipe.ingredients[i].ingredient = merchant.inventory[j].ingredient;
  84. break;
  85. }
  86. }
  87. }
  88. for(let i = 0; i < merchant.recipes.length; i++){
  89. if(recipe._id === merchant.recipes[i]._id){
  90. if(remove){
  91. merchant.recipes.splice(i, 1);
  92. }else{
  93. merchant.recipes[i] = recipe;
  94. index = i;
  95. }
  96. isNew = false;
  97. break;
  98. }
  99. }
  100. if(isNew){
  101. merchant.recipes.push(recipe);
  102. index = merchant.recipes.length - 1;
  103. }
  104. recipeBookStrandObj.populateRecipes();
  105. closeSidebar();
  106. }
  107. /*
  108. Updates an order in the front end
  109. Can create, edit or remove
  110. order = {
  111. _id: id of recipe,
  112. name: name of recipe,
  113. price: price of recipe,
  114. ingredients: [
  115. ingredient: id of ingredient,
  116. quantity: quantity of ingredient
  117. ]
  118. }
  119. */
  120. let updateOrders = (order, remove = false)=>{
  121. let isNew = true;
  122. for(let i = 0; i < orders.length; i++){
  123. if(orders[i]._id === order._id){
  124. if(remove){
  125. orders.splice(i, 1);
  126. }else{
  127. orders[i] = order;
  128. }
  129. isNew = false;
  130. }
  131. }
  132. if(isNew){
  133. orders.push(order);
  134. }
  135. ordersStrandObj.isPopulated = false;
  136. ordersStrandObj.display();
  137. closeSidebar();
  138. }
  139. //Close any open sidebar
  140. let closeSidebar = ()=>{
  141. let sidebar = document.querySelector("#sidebarDiv");
  142. for(let i = 0; i < sidebar.children.length; i++){
  143. sidebar.children[i].style.display = "none";
  144. }
  145. sidebar.classList = "sidebarHide";
  146. }
  147. /*
  148. Open a specific sidebar
  149. Input:
  150. sidebar: the outermost element of the sidebar (must contain class sidebar)
  151. */
  152. let openSidebar = (sidebar)=>{
  153. document.querySelector("#sidebarDiv").classList = "sidebar";
  154. let sideBars = document.querySelector("#sidebarDiv").children;
  155. for(let i = 0; i < sideBars.length; i++){
  156. sideBars[i].style.display = "none";
  157. }
  158. sidebar.style.display = "flex";
  159. }
  160. /*
  161. Gets the indices of two dates from transactions
  162. Inputs
  163. from: starting date
  164. to: ending date (default to now)
  165. Output
  166. Array containing starting index and ending index
  167. Note: Will return false if it cannot find both necessary dates
  168. */
  169. let dateIndices = (from, to = new Date())=>{
  170. let indices = [];
  171. for(let i = 0; i < transactions.length; i++){
  172. if(transactions[i].date > from){
  173. indices.push(i);
  174. break;
  175. }
  176. }
  177. for(let i = transactions.length - 1; i >=0; i--){
  178. if(transactions[i].date < to){
  179. indices.push(i);
  180. break;
  181. }
  182. }
  183. if(indices.length < 2){
  184. return false;
  185. }
  186. return indices;
  187. }
  188. /*
  189. Gets the quantity of each ingredient sold between two dates (dateRange)
  190. Inputs
  191. dateRange: list containing a start date and an end date
  192. Output
  193. List of objects
  194. id: id of specific ingredient
  195. quantity: quantity sold of that ingredient
  196. name: name of the ingredient
  197. */
  198. let ingredientsSold = (dateRange)=>{
  199. if(!dateRange){
  200. return false;
  201. }
  202. let recipes = recipesSold(dateRange);
  203. let ingredientList = [];
  204. for(let i = 0; i < recipes.length; i++){
  205. for(let j = 0; j < merchant.recipes.length; j++){
  206. for(let k = 0; k < merchant.recipes[j].ingredients.length; k++){
  207. let exists = false;
  208. for(let l = 0; l < ingredientList.length; l++){
  209. if(ingredientList[l].id === merchant.recipes[j].ingredients[k].ingredient._id){
  210. exists = true;
  211. ingredientList[l].quantity += merchant.recipes[j].ingredients[k].quantity * recipes[i].quantity;
  212. break;
  213. }
  214. }
  215. if(!exists){
  216. ingredientList.push({
  217. id: merchant.recipes[j].ingredients[k].ingredient._id,
  218. quantity: merchant.recipes[j].ingredients[k].quantity * recipes[i].quantity,
  219. name: merchant.recipes[j].ingredients[k].ingredient.name,
  220. unit: merchant.recipes[j].ingredients[k].ingredient.unit
  221. })
  222. }
  223. }
  224. }
  225. }
  226. return ingredientList;
  227. }
  228. /*
  229. Gets the quantity of a single ingredient sold between two dates (dateRange)
  230. Input:
  231. dateRange: array containing two elements, start and end indices
  232. id: id of the ingredient to calculate
  233. Return: (int) Quantity of recipes sold
  234. */
  235. let ingredientSold = (dateRange, id)=>{
  236. let recipes = recipesSold(dateRange);
  237. let total = 0;
  238. let checkRecipes = [];
  239. let quantities = [];
  240. for(let i = 0; i < merchant.recipes.length; i++){
  241. for(let j = 0; j < merchant.recipes[i].ingredients.length; j++){
  242. if(merchant.recipes[i].ingredients[j].ingredient._id === id){
  243. checkRecipes.push(merchant.recipes[i]._id);
  244. quantities.push(merchant.recipes[i].ingredients[j].quantity);
  245. break;
  246. }
  247. }
  248. }
  249. for(let i = 0; i < recipes.length; i++){
  250. for(let i = 0; i < checkRecipes.length; i++){
  251. if(checkRecipes[i] === recipes[i].id){
  252. total += recipes[i].quantity * quantities[i];
  253. break;
  254. }
  255. }
  256. }
  257. return total;
  258. }
  259. /*
  260. Gets the number of recipes sold between two dates (dateRange)
  261. Inputs:
  262. dateRange: array containing a start date and an end date
  263. Return:
  264. List of objects
  265. id: id of specific recipe
  266. quantity: quantity sold of that recipe
  267. */
  268. let recipesSold = (dateRange)=>{
  269. let recipeList = [];
  270. for(let i = dateRange[0]; i <= dateRange[1]; i++){
  271. for(let j = 0; j < transactions[i].recipes.length; j++){
  272. let exists = false;
  273. for(let k = 0; k < recipeList.length; k++){
  274. if(recipeList[k].id === transactions[i].recipes[j].recipe){
  275. exists = true;
  276. recipeList[k].quantity += transactions[i].recipes[j].quantity;
  277. break;
  278. }
  279. }
  280. if(!exists){
  281. recipeList.push({
  282. id: transactions[i].recipes[j].recipe,
  283. quantity: transactions[i].recipes[j].quantity
  284. })
  285. }
  286. }
  287. }
  288. return recipeList;
  289. }
  290. /*
  291. Groups all of the merchant's ingredients by their category
  292. Return:
  293. Array of objects
  294. name: Category name
  295. ingredients: Array of objects
  296. id: Id of ingredient
  297. name: Name of ingredient
  298. quantity: Merchant's quantity of this ingredient
  299. unit: Measurement unit
  300. */
  301. let categorizeIngredients = (ingredients)=>{
  302. let ingredientsByCategory = [];
  303. for(let i = 0; i < ingredients.length; i++){
  304. let categoryExists = false;
  305. for(let j = 0; j < ingredientsByCategory.length; j++){
  306. if(ingredients[i].ingredient.category === ingredientsByCategory[j].name){
  307. ingredientsByCategory[j].ingredients.push({
  308. id: ingredients[i].ingredient._id,
  309. name: ingredients[i].ingredient.name,
  310. quantity: ingredients[i].quantity,
  311. unit: ingredients[i].ingredient.unit
  312. });
  313. categoryExists = true;
  314. break;
  315. }
  316. }
  317. if(!categoryExists){
  318. ingredientsByCategory.push({
  319. name: ingredients[i].ingredient.category,
  320. ingredients: [{
  321. id: ingredients[i].ingredient._id,
  322. name: ingredients[i].ingredient.name,
  323. quantity: ingredients[i].quantity,
  324. unit: ingredients[i].ingredient.unit
  325. }]
  326. });
  327. }
  328. }
  329. return ingredientsByCategory;
  330. }
  331. let unitizeIngredients = (ingredients)=>{
  332. let ingredientsByUnit = [];
  333. for(let i = 0; i < ingredients.length; i++){
  334. let unitExists = false;
  335. for(let j = 0; j < ingredientsByUnit.length; j++){
  336. if(ingredients[i].ingredient.unit === ingredientsByUnit[j].name){
  337. ingredientsByUnit[j].ingredients.push({
  338. id: ingredients[i].ingredient._id,
  339. name: ingredients[i].ingredient.name,
  340. quantity: ingredients[i].quantity,
  341. unit: ingredients[i].ingredient.unit
  342. });
  343. unitExists = true;
  344. break;
  345. }
  346. }
  347. if(!unitExists){
  348. ingredientsByUnit.push({
  349. name: ingredients[i].ingredient.unit,
  350. ingredients: [{
  351. id: ingredients[i].ingredient._id,
  352. name: ingredients[i].ingredient.name,
  353. quantity: ingredients[i].quantity,
  354. unit: ingredients[i].ingredient.unit
  355. }]
  356. })
  357. }
  358. }
  359. return ingredientsByUnit;
  360. }
  361. let categorizeIngredientsFromDB = (ingredients)=>{
  362. let ingredientsByCategory = [];
  363. for(let i = 0; i < ingredients.length; i++){
  364. let categoryExists = false;
  365. for(let j = 0; j < ingredientsByCategory.length; j++){
  366. if(ingredients[i].category === ingredientsByCategory[j].name){
  367. ingredientsByCategory[j].ingredients.push({
  368. id: ingredients[i]._id,
  369. name: ingredients[i].name,
  370. unit: ingredients[i].unit
  371. });
  372. categoryExists = true;
  373. break;
  374. }
  375. }
  376. if(!categoryExists){
  377. ingredientsByCategory.push({
  378. name: ingredients[i].category,
  379. ingredients: [{
  380. id: ingredients[i]._id,
  381. name: ingredients[i].name,
  382. unit: ingredients[i].unit
  383. }]
  384. });
  385. }
  386. }
  387. return ingredientsByCategory;
  388. }
  389. let recipesForIngredient = (ingredientId)=>{
  390. let recipes = [];
  391. for(let i = 0; i < merchant.recipes.length; i++){
  392. for(let j = 0; j < merchant.recipes[i].ingredients.length; j++){
  393. if(merchant.recipes[i].ingredients[j].ingredient._id === ingredientId){
  394. recipes.push(merchant.recipes[i]);
  395. break;
  396. }
  397. }
  398. }
  399. return recipes;
  400. }
  401. for(let transaction of transactions){
  402. transaction.date = new Date(transaction.date);
  403. }
  404. homeStrandObj.display();