Refactor Home page to Razor component
This commit is contained in:
parent
f070acef41
commit
595a691da2
Groceries
@ -15,7 +15,7 @@
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<NavLink class="sidebar__item" href="/" Match="NavLinkMatch.All">
|
<NavLink class="sidebar__item">
|
||||||
@* receipt long icon *@
|
@* receipt long icon *@
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24"><path d="M0,0h24v24H0V0z" fill="none"/><g><path d="M19.5,3.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2v14H3v3c0,1.66,1.34,3,3,3h12c1.66,0,3-1.34,3-3V2 L19.5,3.5z M15,20H6c-0.55,0-1-0.45-1-1v-1h10V20z M19,19c0,0.55-0.45,1-1,1s-1-0.45-1-1v-3H8V5h11V19z"/><rect height="2" width="6" x="9" y="7"/><rect height="2" width="2" x="16" y="7"/><rect height="2" width="6" x="9" y="10"/><rect height="2" width="2" x="16" y="10"/></g></svg>
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24"><path d="M0,0h24v24H0V0z" fill="none"/><g><path d="M19.5,3.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2v14H3v3c0,1.66,1.34,3,3,3h12c1.66,0,3-1.34,3-3V2 L19.5,3.5z M15,20H6c-0.55,0-1-0.45-1-1v-1h10V20z M19,19c0,0.55-0.45,1-1,1s-1-0.45-1-1v-3H8V5h11V19z"/><rect height="2" width="6" x="9" y="7"/><rect height="2" width="2" x="16" y="7"/><rect height="2" width="6" x="9" y="10"/><rect height="2" width="2" x="16" y="10"/></g></svg>
|
||||||
Lists
|
Lists
|
||||||
|
@ -1,47 +1,14 @@
|
|||||||
namespace Groceries.Home;
|
namespace Groceries.Home;
|
||||||
|
|
||||||
using Groceries.Data;
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
[Route("/")]
|
[Route("/")]
|
||||||
public class HomeController : Controller
|
public class HomeController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppDbContext dbContext;
|
|
||||||
|
|
||||||
public HomeController(AppDbContext dbContext)
|
|
||||||
{
|
|
||||||
this.dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> IndexAsync()
|
public IResult Index()
|
||||||
{
|
{
|
||||||
var randomTagQuantity = await dbContext.ItemTagQuantities
|
return new RazorComponentResult<HomePage>();
|
||||||
.FromSql($"""
|
|
||||||
SELECT tag, quantity, coalesce(unit_name, unit) AS unit, is_metric, is_divisible
|
|
||||||
FROM (
|
|
||||||
SELECT
|
|
||||||
unnest(tags) AS tag,
|
|
||||||
round(sum((item_quantity->'amount')::numeric * quantity), 1) AS quantity,
|
|
||||||
item_quantity->>'unit' AS unit,
|
|
||||||
(item_quantity->'is_metric')::boolean AS is_metric,
|
|
||||||
(item_quantity->'is_divisible')::boolean AS is_divisible
|
|
||||||
FROM item_purchases
|
|
||||||
JOIN items USING (item_id)
|
|
||||||
CROSS JOIN item_quantity(name)
|
|
||||||
WHERE array_length(tags, 1) > 0
|
|
||||||
AND age(created_at) <= '90 days'
|
|
||||||
AND item_quantity IS NOT NULL
|
|
||||||
GROUP BY tag, item_quantity->>'unit', item_quantity->'is_metric', item_quantity->'is_divisible'
|
|
||||||
ORDER BY random()
|
|
||||||
FETCH FIRST ROW ONLY
|
|
||||||
) AS random_item_tag_quantity
|
|
||||||
LEFT JOIN item_tags USING (tag)
|
|
||||||
""")
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return View(randomTagQuantity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
Groceries/Home/HomePage.razor
Normal file
79
Groceries/Home/HomePage.razor
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
@using Groceries.Data
|
||||||
|
@using Humanizer
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
|
||||||
|
@layout Layout
|
||||||
|
|
||||||
|
@inject AppDbContext DbContext
|
||||||
|
@inject IHttpContextAccessor HttpContextAccessor
|
||||||
|
|
||||||
|
<HeadContent>
|
||||||
|
<meta name="turbo-cache-control" content="no-preview" />
|
||||||
|
</HeadContent>
|
||||||
|
|
||||||
|
<PageTitle>Groceries</PageTitle>
|
||||||
|
|
||||||
|
<section class="card">
|
||||||
|
<header class="card__header">
|
||||||
|
<h2>Item Quantity (last 90 days)</h2>
|
||||||
|
</header>
|
||||||
|
<div class="card__content">
|
||||||
|
@if (model != null)
|
||||||
|
{
|
||||||
|
if (model.IsDivisible)
|
||||||
|
{
|
||||||
|
var quantity = Convert.ToDouble(model.Quantity);
|
||||||
|
var weekQuantity = Math.Round(quantity / 12);
|
||||||
|
|
||||||
|
<strong>@(model.IsMetric ? quantity.ToMetric() : quantity)@model.Unit @model.Tag</strong>
|
||||||
|
<small>(@(model.IsMetric ? weekQuantity.ToMetric() : weekQuantity)@model.Unit per week)</small>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var name = model.Unit != null ? $"{model.Tag} {model.Unit}" : model.Tag;
|
||||||
|
|
||||||
|
var averageQuantity = model.Quantity / 12;
|
||||||
|
var averagePeriod = "week";
|
||||||
|
if (averageQuantity < 1)
|
||||||
|
{
|
||||||
|
averageQuantity *= 4;
|
||||||
|
averagePeriod = "month";
|
||||||
|
}
|
||||||
|
|
||||||
|
<strong>@name.ToQuantity(Convert.ToInt32(model.Quantity))</strong>
|
||||||
|
<small>(@name.ToQuantity(Convert.ToInt32(averageQuantity)) per @averagePeriod)</small>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private ItemTagQuantity? model;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
model = await DbContext.ItemTagQuantities
|
||||||
|
.FromSqlRaw(@"
|
||||||
|
SELECT tag, quantity, coalesce(unit_name, unit) AS unit, is_metric, is_divisible
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
unnest(tags) AS tag,
|
||||||
|
round(sum((item_quantity->'amount')::numeric * quantity), 1) AS quantity,
|
||||||
|
item_quantity->>'unit' AS unit,
|
||||||
|
(item_quantity->'is_metric')::boolean AS is_metric,
|
||||||
|
(item_quantity->'is_divisible')::boolean AS is_divisible
|
||||||
|
FROM item_purchases
|
||||||
|
JOIN items USING (item_id)
|
||||||
|
CROSS JOIN item_quantity(name)
|
||||||
|
WHERE array_length(tags, 1) > 0
|
||||||
|
AND age(created_at) <= '90 days'
|
||||||
|
AND item_quantity IS NOT NULL
|
||||||
|
GROUP BY tag, item_quantity->>'unit', item_quantity->'is_metric', item_quantity->'is_divisible'
|
||||||
|
ORDER BY random()
|
||||||
|
FETCH FIRST ROW ONLY
|
||||||
|
) AS random_item_tag_quantity
|
||||||
|
LEFT JOIN item_tags USING (tag)
|
||||||
|
")
|
||||||
|
.FirstOrDefaultAsync(HttpContextAccessor.HttpContext!.RequestAborted);
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
@using Groceries.Data
|
|
||||||
@using Humanizer
|
|
||||||
|
|
||||||
@model ItemTagQuantity?
|
|
||||||
|
|
||||||
@section head {
|
|
||||||
@*<meta name="turbo-cache-control" content="no-preview" />*@
|
|
||||||
}
|
|
||||||
|
|
||||||
<section class="card">
|
|
||||||
<header class="card__header">
|
|
||||||
<h2>Item Quantity (last 90 days)</h2>
|
|
||||||
</header>
|
|
||||||
<div class="card__content">
|
|
||||||
@if (Model != null)
|
|
||||||
{
|
|
||||||
@if (Model.IsDivisible)
|
|
||||||
{
|
|
||||||
var quantity = Convert.ToDouble(Model.Quantity);
|
|
||||||
var weekQuantity = Math.Round(quantity / 12);
|
|
||||||
|
|
||||||
<strong>@(Model.IsMetric ? quantity.ToMetric() : quantity)@Model.Unit @Model.Tag</strong>
|
|
||||||
<small>(@(Model.IsMetric ? weekQuantity.ToMetric() : weekQuantity)@Model.Unit per week)</small>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var name = Model.Unit != null ? $"{Model.Tag} {Model.Unit}" : Model.Tag;
|
|
||||||
|
|
||||||
var avgQuantity = Model.Quantity / 12;
|
|
||||||
var avgPeriod = "week";
|
|
||||||
if (avgQuantity < 1)
|
|
||||||
{
|
|
||||||
avgQuantity *= 4;
|
|
||||||
avgPeriod = "month";
|
|
||||||
}
|
|
||||||
|
|
||||||
<strong>@name.ToQuantity(Convert.ToInt32(Model.Quantity))</strong>
|
|
||||||
<small>(@name.ToQuantity(Convert.ToInt32(avgQuantity)) per @avgPeriod)</small>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
Loading…
x
Reference in New Issue
Block a user