The make button is pretty much done, just need to finish up by rate limiting it. That will take place in the engagement repository. Sharing works as well, just a UI change, there is no backend yet, maybe there should be an engagement type for sharing recipes. But not totally sure. The viewing is also in a semi-working state. It does not create requests for users that aren't signed in, which needs to come. With that update there is a need to update HOW the requests come in, we don't need it every time we load the page. Maybe just when we click to it, from somewhere else? Finally, the favoriting does not totally work. The entry into the engagement table is complete, but the actual favorites table, favorite creation, button toggling AND button rendering is not implemented yet.
127 lines
4.6 KiB
Plaintext
127 lines
4.6 KiB
Plaintext
package templates
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/haydenhargreaves/Potion/internal/domain/recipe"
|
|
domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
|
|
domainServer "github.com/haydenhargreaves/Potion/internal/domain/server"
|
|
"github.com/haydenhargreaves/Potion/internal/templates/components"
|
|
)
|
|
|
|
templ SearchPage(filters domainRecipe.SearchFilters, searchOnLoad bool) {
|
|
@components.Navbar("")
|
|
<div class="w-full flex justify-center">
|
|
<div
|
|
class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 min-h-screen border-l border-r border-gray-300
|
|
bg-white flex flex-col items-center"
|
|
>
|
|
@components.BannerText("Recipe Search")
|
|
@components.SearchBar(filters, false, searchOnLoad)
|
|
<hr class="text-gray-300 w-full"/>
|
|
@ResultList(nil)
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
templ ResultList(recipes []domain.Recipe) {
|
|
<div id="result-list" class="flex flex-col w-full p-4 items-center">
|
|
for _, recipe := range recipes {
|
|
@searchResult(recipe)
|
|
}
|
|
if len(recipes) == 0 || recipes == nil {
|
|
<p class="text-gray-700 text-sm py-4">No results</p>
|
|
} else {
|
|
<p class="text-gray-700 text-sm py-4">End of results</p>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ searchResult(recipe domain.Recipe) {
|
|
<a
|
|
href={ templ.SafeURL(fmt.Sprintf(domainServer.WEB_RECIPE, recipe.Id)) }
|
|
class="w-full p-2 border-b border-gray-200 hover:bg-gray-100 duration-200 flex items-center flex-col md:flex-row even:bg-[#f8f8f8]"
|
|
>
|
|
<img class="bg-gray-50 size-56 md:size-40 rounded-md border-0" src=""/>
|
|
<div class="text-gray-700 p-4 flex flex-col items-center md:items-start">
|
|
<h3 class="text-xl font-semibold text-black pb-1">
|
|
{ recipe.Title } <span class="text-sm font-normal hidden md:inline">{ recipe.Category }</span>
|
|
</h3>
|
|
<div class="text-sm flex gap-x-3 gap-y-1 items-center flex-wrap">
|
|
<span class="flex gap-x-1 align-center">
|
|
@timeIconSm()
|
|
{ recipe.Duration.Total } min
|
|
</span>
|
|
<span class="flex gap-x-1 align-center">
|
|
for _ = range(recipe.Difficulty) {
|
|
@starIconSm(true)
|
|
}
|
|
for _ = range(5 - recipe.Difficulty) {
|
|
@starIconSm(false)
|
|
}
|
|
</span>
|
|
<span class="flex gap-x-1 align-center">
|
|
@servingIconSm()
|
|
Serves { recipe.Serves }
|
|
</span>
|
|
</div>
|
|
<p class="text-sm py-2 text-center md:text-left">{ recipe.Description }</p>
|
|
</div>
|
|
</a>
|
|
}
|
|
|
|
templ servingIconSm() {
|
|
<svg
|
|
class="h-5 text-blue-600"
|
|
fill="currentColor"
|
|
version="1.1"
|
|
id="Icons"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
viewBox="0 0 32 32"
|
|
xml:space="preserve"
|
|
>
|
|
<g>
|
|
<circle cx="12" cy="16" r="5"></circle>
|
|
<path
|
|
d="M12,6C6.5,6,2,10.5,2,16s4.5,10,10,10s10-4.5,10-10S17.5,6,12,6z M12,23c-3.9,0-7-3.1-7-7s3.1-7,7-7s7,3.1,7,7
|
|
S15.9,23,12,23z"
|
|
></path>
|
|
<path
|
|
d="M30,10.5V5c0-0.6-0.4-1-1-1s-1,0.4-1,1v5.5c0,0.2,0,0.4,0,0.5h-1V5c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-1c0-0.2,0-0.4,0-0.5V5
|
|
c0-0.6-0.4-1-1-1s-1,0.4-1,1v5.5c0,1.9,0.5,3.4,1.4,4.3c0.7,0.8,1,1.8,0.9,2.7l-1,7.3c-0.1,0.8,0.1,1.6,0.6,2.2S25.2,28,26,28
|
|
s1.5-0.3,2.1-0.9s0.8-1.4,0.6-2.2l-1-7.3c-0.1-1,0.2-2,0.9-2.8C29.5,13.8,30,12.3,30,10.5z"
|
|
></path>
|
|
</g>
|
|
</svg>
|
|
}
|
|
|
|
templ timeIconSm() {
|
|
<svg class="h-5 text-blue-600" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="M12 7V12L14.5 13.5M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
|
|
stroke="currentColor"
|
|
stroke-width="1.5"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
></path>
|
|
</svg>
|
|
}
|
|
|
|
templ starIconSm(filled bool) {
|
|
if filled {
|
|
<svg class="h-4 text-blue-600" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="M23.632 9.201a.628.628 0 0 1-.22.678l-5.726 4.96 1.727 7.394a.606.606 0 0 1-.935.676l-6.503-3.953-6.503 3.953a.713.713 0 0 1-.374.112.57.57 0 0 1-.34-.109.629.629 0 0 1-.222-.679l1.729-7.393L.539 9.879A.607.607 0 0 1 .897 8.78l7.536-.635 2.965-7.083a.62.62 0 0 1 1.155.001l2.965 7.082 7.536.635a.63.63 0 0 1 .578.42z"
|
|
></path>
|
|
<path fill="none" d="M0 0h24v24H0z"></path>
|
|
</svg>
|
|
} else {
|
|
<svg class="h-4 text-gray-500" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="M23.054 8.781l-7.536-.635-2.965-7.082a.619.619 0 0 0-1.155 0L8.433 8.145.896 8.78a.607.607 0 0 0-.357 1.1l5.726 4.96-1.729 7.395a.63.63 0 0 0 .223.679.573.573 0 0 0 .339.108.717.717 0 0 0 .374-.111l6.503-3.954 6.503 3.953a.606.606 0 0 0 .935-.677l-1.727-7.392 5.725-4.96a.607.607 0 0 0-.357-1.099zm-6.48 5.698l1.662 7.113-6.261-3.806-6.262 3.807 1.663-7.114-5.513-4.776 7.257-.611 2.855-6.817 2.855 6.817 7.257.611z"
|
|
></path>
|
|
<path fill="none" d="M0 0h24v24H0z"></path>
|
|
</svg>
|
|
}
|
|
}
|