enhanced client side experience
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Unbinder.Repositories;
|
||||
|
||||
namespace Unbinder.Controllers.Api
|
||||
{
|
||||
public abstract class BaseApiController<T> : ControllerBase where T : class
|
||||
{
|
||||
protected readonly IBaseRepository<T> repository;
|
||||
|
||||
public BaseApiController(IBaseRepository<T> repository)
|
||||
{
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public IActionResult UpdateById(int id)
|
||||
{
|
||||
var result = repository.UpdateById(id);
|
||||
if (result == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult DeleteById(int id)
|
||||
{
|
||||
var result = repository.DeleteById(id);
|
||||
if (result == 0)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,22 @@ using Unbinder.Repositories;
|
||||
|
||||
namespace Unbinder.Controllers.Api
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class RecipeApiController : BaseApiController<Recipe>
|
||||
public class RecipeApiController(IRecipeRepository _repository) : ControllerBase
|
||||
{
|
||||
public RecipeApiController(IRecipeRepository recipeRepository) : base(recipeRepository)
|
||||
private readonly IRecipeRepository repository = _repository;
|
||||
|
||||
[HttpGet]
|
||||
[Route("/api/recipe/search")]
|
||||
public IActionResult Search([FromQuery] string? q)
|
||||
{
|
||||
if (q == null) return Ok(repository.GetAll);
|
||||
|
||||
var result = repository.GetAll?.Where(r => r.Name.Contains(q, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return result == null
|
||||
? NotFound()
|
||||
: Ok(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Unbinder.Controllers
|
||||
}
|
||||
|
||||
[Route("[controller]/search")]
|
||||
public IActionResult Search([FromQuery] string? q, string? category)
|
||||
public IActionResult Search([FromQuery] string? q, [FromQuery] string? category)
|
||||
{
|
||||
if (q == null && category == null) return View(_recipeRepository.GetAll);
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
||||
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
|
||||
//builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
|
||||
// .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
|
||||
|
||||
builder.Services.AddAuthorization(options =>
|
||||
// By default, all incoming requests will be authorized according to the default policy.
|
||||
options.FallbackPolicy = options.DefaultPolicy);
|
||||
//builder.Services.AddAuthorization(options =>
|
||||
// // By default, all incoming requests will be authorized according to the default policy.
|
||||
// options.FallbackPolicy = options.DefaultPolicy);
|
||||
|
||||
builder.Services.AddDbContext<UnbinderDbContext>(options =>
|
||||
options.UseSqlServer(connectionString));
|
||||
@@ -27,6 +27,16 @@ builder.Services.AddDbContext<UnbinderDbContext>(options =>
|
||||
builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddRazorPages();
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("AllowAll", builder =>
|
||||
{
|
||||
builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddScoped<IRecipeRepository, RecipeRepository>();
|
||||
builder.Services.AddScoped<IIngredientRepository, IngredientRepository>();
|
||||
|
||||
@@ -45,8 +55,8 @@ if (!app.Environment.IsDevelopment())
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
//app.UseAuthentication();
|
||||
//app.UseAuthorization();
|
||||
|
||||
app.MapDefaultControllerRoute();
|
||||
|
||||
|
||||
@@ -1,20 +1,52 @@
|
||||
@model IEnumerable<Recipe>
|
||||
|
||||
<div>
|
||||
<p id="displayed-query-string"></p>
|
||||
@foreach (var recipe in @Model)
|
||||
{
|
||||
<p>@recipe.Name</p>
|
||||
<p>@recipe.RecipeText</p>
|
||||
}
|
||||
<div id="search-page-header" class="mb-8 border-white border-b">
|
||||
<h3 id="query-message"></h3>
|
||||
<input class="text-black" id="new-search-query" type="text" />
|
||||
<button id="execute-search">Search</button>
|
||||
</div>
|
||||
<div id="search-results">
|
||||
@foreach (var recipe in @Model)
|
||||
{
|
||||
<p>@recipe.Name</p>
|
||||
<p>@recipe.RecipeText</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
const query = window.location.search?.split("=")[1];
|
||||
const target = document.getElementById("displayed-query-string");
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// dom elements
|
||||
const query = window.location.search?.split("=")[1];
|
||||
const message = document.getElementById("query-message");
|
||||
const textField = document.getElementById("new-search-query");
|
||||
const searchButton = document.getElementById("execute-search");
|
||||
const searchResultsContainer = document.getElementById("search-results");
|
||||
|
||||
if (query) {
|
||||
target.innerHTML = `Viewing ${@Model.ToArray().Length} results for: ${query}`;
|
||||
} else {
|
||||
target.innerHTML = "Enter a new search term below:";
|
||||
}
|
||||
console.log(query);
|
||||
|
||||
// set initial message value
|
||||
if (query) {
|
||||
message.innerHTML = `Viewing ${@Model.ToArray().Length} results for: ${query}`;
|
||||
} else {
|
||||
message.innerHTML = "Enter a new search term below:";
|
||||
}
|
||||
|
||||
// handle search updates on client side
|
||||
searchButton.onclick = async () => {
|
||||
const newResult = await fetch(`/api/recipe/search?q=${textField.value}`);
|
||||
|
||||
console.log(newResult);
|
||||
|
||||
const newResultJson = await newResult.json();
|
||||
window.location.search = `?q=${textField.value}`;
|
||||
searchResultsContainer.innerHTML = `@{
|
||||
foreach (var recipe in @Model)
|
||||
{
|
||||
<p>@recipe.Name</p>
|
||||
<p>@recipe.RecipeText</p>
|
||||
}
|
||||
}`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user