== ID: 1
1. Корисникот пишува во полето за пребарување состојки, што активира AJAX повик до /Recipes/getSuggestions акцијата по 300ms задоцнување за да ги добие соодветните состојки од базата на податоци.
2. searchIngredients() прави fetch(/Recipes/getSuggestions?query=${encodeURIComponent(query)}) со GET метод. Одговорот се парсира со response.json() и се прикажува преку displaySuggestions().
3. displaySuggestions() користи document.createElement("div") за секој резултат, сетира innerHTML со regex name.replace(regex, "$1") за highlighting, и поставува addEventListener("click") за селекција.
4. Избраните состојки се чуваат во selectedIngredients[] низа со структура {Id, Name, Quantity, Unit}. addIngredient() прави selectedIngredients.push(newIngredient) и повикува updateIngredientsDisplay() и updateIngredientsInput()
5. updateIngredientsInput() користи JSON.stringify(selectedIngredients) за да ја конвертира низата во string и ги сетира во hiddenIngredientsInput.value за испраќање преку формата
6. initializeFileUpload() поставува addEventListener("dragover"), addEventListener("drop"), и FileReader() API за preview на сликата со reader.readAsDataURL(file)
7. showAddIngredientModal() го прикажува модалниот прозорец за додавање на нова состојка што ја нема во базата. handleAddNewIngredient() прави POST до /Recipes/AddIngredient каде состојката се додава во базата но со "Pending" статус
8. При испраќање, контролерот:
- Ја зачувува прикачената слика во /wwwroot/images/ со уникатно име
- Креира запис за рецептот со ID на корисникот и основни информации
- Ја изминува низата од состојките за да креира записи во RecipeIngredient
- Пресметува вкупни нутритривни вредности користејќи ConvertType() метод
- Генерира тагови за типот на рецептот користејќи GenerateRecipeTags()
== ID: 2
1. Корисникот го клика рецептот што сака да го избрише од "My Recipes" секцијата
2. Корисникот клика на копчето за бришење со што се прави повик до /Recipes/Delete акцијата која го враќа "_RecipeDeletePartial"
3. Корисникот го потврдува бришењето на рецептот со што се прави повик до /Recipes/DeleteConfirmed акцијата која го брише записот за избраниот рецепт
== ID: 3
1. /Recipes/Index акцијата користи .Where(r => r.RecipeStatus == "Accepted") за да ги филтрира одобрените рецепти, потоа .Skip((page - 1) * pageSize).Take(pageSize) за пагинација.
2. initializeInfiniteScroll() поставува event listener кој проверува scrollTop + windowHeight >= documentHeight - 600 за да открие кога корисникот е близу крајот. loadMoreRecipes() испраќа GET барање до /Recipes/Index акцијата.
3. createRecipeCard() динамички креира div елементи со data-calories, data-protein, data-carbs, data-fat атрибути кои се користат за филтрирање.
4. updateSlider() чита parseInt(minSlider.value) и parseInt(maxSlider.value), ги споредува вредностите со if (minVal > maxVal), и сетира CSS left и width на .range-fill елементот за визуелниот приказ на самите слајдери.
5. filterRecipes() користи document.querySelectorAll(".recipe-card") за да ги добие сите картички, потоа за секоја прави:
- parseInt(card.dataset.calories) за филтрирање според макро вредности
- .textContent.toLowerCase() за текстуално пребарување
- .getAttribute("data-favorited") === "true" за приказ на омилени
== ID: 4
1. currentFilters објектот ги чува вредностите од слајдерите, додека initializeFilters() поставува event listeners на сите 8 slider inputs со addEventListener("input").
2. updateSlider() синхронизира min/max вредности со if (minVal > maxVal) validation, ажурира CSS, и повикува applyFilters() за да ги зачува вредностите во currentFilters објектот.
3. openMenu(restaurantId) се активира на click, конструира query parameters објект од current filter state, и прави new URLSearchParams(f).toString() за URL encoding на филтрите.
4. fetch(/Restaurants/GetRestaurantMeals/${restaurantId}?${query}) испраќа GET барање со филтер параметри како query string до контролерот.
5. Контролерот прима nullable integers int? minCalories, int? maxCalories... што ASP.NET ги bind-ува од query string автоматски.
6. .Where() применува range filtering со логика (minCalories == null || r.Calories >= minCalories) за секој макронутриент.
7. Контролерот враќа PartialView("_RestaurantMealsPartial", filteredMeals), кој fetch го зема како .text() response.
8. JavaScript го вметнува HTML од филтрираните оброци во модалот преку menuContainer.innerHTML = html, прикажувајќи само оброци што ги исполнуваат критериумите поставени на клиентската страна.
== ID: 5
1. [BindProperty] InputModel Input автоматски ги bind-ува HTML form полињата со C# својствата. Data annotations [Required], [EmailAddress], [StringLength(100, MinimumLength = 6)] обезбедуваат client и server-side validation.
2. OnPostAsync() прво проверува ModelState.IsValid за server-side validation, потоа повикува CreateUser() за да креира нова User instance користејќи Activator.CreateInstance() reflection.
3. _userStore.SetUserNameAsync() и _emailStore.SetEmailAsync() ги сетираат username-от и еmail-от, додека _userManager.CreateAsync(user, Input.Password) го креира записот во базата со хаширан пасворд преку Identity framework-от.
4. _signInManager.SignInAsync(user, isPersistent: false) автоматски го логира и го пренасочува кон returnUrl.
== ID: 6
1. [BindProperty] InputModel Input автоматски ги bind-ува email и password полињата преку ASP.NET model binding. Data annotations [Required], [EmailAddress], [DataType(DataType.Password)] обезбедуваат валидација.
2. OnPostAsync() прави ModelState.IsValid проверка, потоа повикува _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false) за автентикација според базата.
3. result.Succeeded е проверка за успешна најава и прави LocalRedirect(returnUrl).
4. Успешната најава креира authentication cookie преку Identity framework што се користи при наредни requests.
== ID: 7
1. showRecipeDetails(recipeId) се активира при клик, додава loading класа на картичката, и конструира query parameters со new URLSearchParams() за да прати isOwner и recipeDetailsDisplayContorol параметри.
2. fetch(/Recipes/Details/${recipeId}?${params}) прави GET request и го зема response како .text() бидејќи се враќа HTML partial view.
3. GetRatingDataAsync() во контролерот ги пресметува averageRating, totalRatings, userRating, и hasUserRated од database, додека _context.FavoriteRecipes.AnyAsync() проверува favorite статус.
4. Контролерот ги поставува ViewBag вредности (IsOwner, AverageRating, IsFavorited) што се користат во partial view за условен приказ на елементите.
5. JavaScript го вметнува partial view-то во modalContainer.innerHTML = html, потоа динамички извршува