dashboards/Cookbook/pages/browse.ps1
|
$browse = New-UDPage -Name "Browse" -Url "/browse" -Content { # QueryString is available in PSU Pages if (-not $Query) { $Query = @{} } $tagFilter = $Query["tag"] $search = $Query["q"] $favOnly = ($Query["fav"] -eq "1") New-UDStyle -Style @" :root { --lilac: #B58CFF; --lilac-dark: #8E6BFF; --border: rgba(181, 140, 255, 0.22); --text: #241A37; --muted: rgba(36, 26, 55, 0.70); } .page-wrap { padding: 18px; border-radius: 18px; background: radial-gradient(circle at 20% 0%, rgba(181,140,255,0.14) 0%, transparent 42%), radial-gradient(circle at 100% 25%, rgba(181,140,255,0.10) 0%, transparent 45%), linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(250,248,255,1) 100%); } .mini-card { border-radius: 18px !important; border: 1px solid var(--border) !important; box-shadow: 0 14px 34px rgba(0,0,0,0.07) !important; overflow: hidden; background: rgba(255,255,255,0.95) !important; } .btn-primary button { border-radius: 14px !important; background: var(--lilac-dark) !important; color: white !important; font-weight: 950 !important; text-transform: none !important; } .btn-ghost button { border-radius: 14px !important; background: rgba(181, 140, 255, 0.08) !important; border: 1px solid rgba(181, 140, 255, 0.25) !important; color: var(--lilac-dark) !important; font-weight: 950 !important; text-transform: none !important; } /* Category Chips Styling */ .MuiChip-root { font-weight: 700 !important; font-size: 13px !important; height: 36px !important; border-radius: 18px !important; transition: all 0.2s ease !important; } .MuiChip-outlined { border: 1.5px solid rgba(181, 140, 255, 0.35) !important; background: linear-gradient(135deg, rgba(181, 140, 255, 0.06), rgba(142, 107, 255, 0.08)) !important; color: #6E4DFF !important; } .MuiChip-outlined:hover { border-color: rgba(181, 140, 255, 0.55) !important; background: linear-gradient(135deg, rgba(181, 140, 255, 0.12), rgba(142, 107, 255, 0.16)) !important; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(181, 140, 255, 0.25) !important; } .MuiChip-colorPrimary { border: 1.5px solid rgba(142, 107, 255, 0.60) !important; background: linear-gradient(135deg, #8E6BFF, #B58CFF) !important; color: white !important; box-shadow: 0 4px 14px rgba(142, 107, 255, 0.35) !important; } .MuiChip-colorPrimary:hover { background: linear-gradient(135deg, #7A57E5, #9D72E5) !important; transform: translateY(-1px); box-shadow: 0 6px 18px rgba(142, 107, 255, 0.45) !important; } .MuiChip-label { padding: 0 14px !important; } .fav-toggle button { border-radius: 999px !important; border: 1px solid rgba(181,140,255,0.35) !important; background: rgba(181,140,255,0.08) !important; color: #6E4DFF !important; font-weight: 950 !important; text-transform: none !important; padding: 8px 14px !important; } .fav-toggle-on button { border-radius: 999px !important; border: 1px solid rgba(181,140,255,0.55) !important; background: var(--lilac-dark) !important; color: white !important; font-weight: 950 !important; text-transform: none !important; padding: 8px 14px !important; } .muted { color: var(--muted) !important; } .title { font-weight: 950 !important; color: var(--text) !important; line-height: 1.15 !important; } .statline { display: flex; gap: 10px; margin-top: 8px; flex-wrap: wrap; } .statpill { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; border: 1px solid rgba(181, 140, 255, 0.25); background: rgba(181, 140, 255, 0.08); color: var(--text); font-weight: 800; font-size: 12px; user-select: none; } .card-img { width: 100%; height: 160px; object-fit: cover; display: block; } .card-img-placeholder { width: 100%; height: 160px; background: linear-gradient(120deg, rgba(181,140,255,0.30), rgba(142,107,255,0.12)); } "@ -Content { New-UDElement -Tag "div" -Attributes @{ className = "page-wrap" } -Content { # Header Row New-UDStack -Direction row -JustifyContent space-between -AlignItems center -Content { New-UDStack -Direction column -Spacing 0 -Content { New-UDTypography -Text "Browse" -Variant overline -Style @{ color = "rgba(36,26,55,0.55)"; fontWeight = "900" } $title = if ($tagFilter) { "Category: $tagFilter" } elseif ($favOnly) { "Favorites" } else { "All Recipes" } New-UDTypography -Text $title -Variant h4 -ClassName "title" if ($search) { New-UDTypography -Text "Search: $search" -Variant body2 -ClassName "muted" } } New-UDStack -Direction row -Spacing 1 -Content { New-UDButton -Text "Back" -ClassName "btn-ghost" -OnClick { Invoke-UDRedirect -Url "/" } New-UDButton -Text "Add Recipe" -ClassName "btn-primary" -OnClick { Show-RecipeModal -RecipeId 0 -SyncId @("recipeCards", "tagChips") } } } New-UDHtml -Markup "<div style='height:14px;'></div>" # Search Bar + Favorites Toggle New-UDStack -Direction row -Spacing 1 -AlignItems center -Content { New-UDTextbox -Id "browseSearchBox" -Placeholder "Search recipes..." -FullWidth -Value ($search ?? "") New-UDButton -Text "Search" -ClassName "btn-primary" -OnClick { $q = (Get-UDElement -Id "browseSearchBox").value $url = Get-BrowseUrl -Tag $tagFilter -Q $q -Fav $favOnly Invoke-UDRedirect -Url $url } # Favorites toggle New-UDButton -Text ($favOnly ? "★ Favorites" : "☆ Favorites") -ClassName ($favOnly ? "fav-toggle-on" : "fav-toggle") -OnClick { $newFav = -not $favOnly $q = (Get-UDElement -Id "browseSearchBox").value $url = Get-BrowseUrl -Tag $tagFilter -Q $q -Fav $newFav Invoke-UDRedirect -Url $url } if ($search -or $tagFilter -or $favOnly) { New-UDButton -Text "Clear" -ClassName "btn-ghost" -OnClick { Invoke-UDRedirect -Url "/browse" } } } New-UDHtml -Markup "<div style='height:16px;'></div>" # Categories / Tag Chips New-UDDynamic -Id "tagChips" -Content { $tags = Get-Tag -Limit 40 New-UDTypography -Text "Categories" -Variant h6 -Style @{ fontWeight = "950"; color = "#241A37"; marginBottom = "10px" } if (-not $tags) { New-UDTypography -Text "No categories yet — add tags when saving recipes." -Variant body2 -ClassName "muted" } else { New-UDStack -Direction row -Spacing 1 -Content { if ($tagFilter) { New-UDChip -Label "All" -OnClick { $url = Get-BrowseUrl -Tag $null -Q $search -Fav $favOnly Invoke-UDRedirect -Url $url } } foreach ($t in @($tags)) { $name = $t.Name $count = [int]($t.RecipeCount ?? 0) $selected = ($tagFilter -and $tagFilter -eq $name) New-UDChip -Label "$name ($count)" -Variant ($selected ? "default" : "outlined") -Color ($selected ? "primary" : "default") -OnClick { $url = Get-BrowseUrl -Tag $name -Q $search -Fav $favOnly Invoke-UDRedirect -Url $url } } } } } New-UDHtml -Markup "<div style='height:16px;'></div>" # Recipe Cards New-UDDynamic -Id "recipeCards" -Content { $recipes = if ($tagFilter) { Get-RecipeByTag -TagName $tagFilter } elseif ($search) { Get-Recipe -Search $search -FavoriteOnly:($favOnly) } else { Get-Recipe -FavoriteOnly:($favOnly) } if (-not $recipes) { New-UDCard -ClassName "mini-card" -Content { New-UDTypography -Text "No recipes found." -Variant h6 -Style @{ fontWeight = "950"; color = "#241A37" } New-UDTypography -Text "Try another search, change filters, or add a recipe." -Variant body2 -ClassName "muted" } return } New-UDGrid -Container -Spacing 2 -Content { foreach ($r in @($recipes)) { $rid = [int]$r.RecipeId $isFav = ([int]($r.IsFavorite ?? 0)) -eq 1 New-UDGrid -Item -ExtraSmallSize 12 -SmallSize 6 -MediumSize 4 -LargeSize 3 -Content { New-UDElement -Tag "div" -Attributes @{ style = @{ position = "relative" } } -Content { New-UDCard -ClassName "mini-card" -Content { $imgPath = Get-RecipeImagePath -RecipeId $rid if ($imgPath) { New-UDImage -Path $imgPath -ClassName "card-img" } else { New-UDElement -Tag "div" -Attributes @{ className = "card-img-placeholder" } -Content { } } New-UDElement -Tag "div" -Attributes @{ style = @{ padding = "14px" } } -Content { New-UDTypography -Text $r.Title -Variant h6 -Style @{ fontWeight = "950" color = "#241A37" margin = "0" lineHeight = "1.15" } if ($r.Description) { New-UDTypography -Text $r.Description -Variant body2 -Style @{ marginTop = "6px" color = "rgba(36,26,55,0.72)" lineHeight = "1.35" } } New-UDElement -Tag "div" -Attributes @{ className = "statline" } -Content { if (($r.PrepTimeMin ?? 0) -gt 0) { New-UDHtml -Markup "<span class='statpill'>⏱️ $($r.PrepTimeMin)m</span>" } if (($r.CookTimeMin ?? 0) -gt 0) { New-UDHtml -Markup "<span class='statpill'>🔥 $($r.CookTimeMin)m</span>" } if (($r.Servings ?? 0) -gt 0) { New-UDHtml -Markup "<span class='statpill'>🍽️ $($r.Servings)</span>" } } New-UDHtml -Markup "<div style='height:10px;'></div>" New-UDStack -Direction row -JustifyContent space-between -AlignItems center -Content { New-UDButton -Text "View" -ClassName "btn-ghost" -OnClick { Invoke-UDRedirect -Url "/recipe/$rid" } New-UDStack -Direction row -Spacing 1 -Content { New-UDButton -Text "Edit" -ClassName "btn-ghost" -OnClick { Show-RecipeModal -RecipeId $rid -SyncId @("recipeCards", "tagChips") } New-UDButton -Text ($isFav ? "★" : "☆") -Variant text -OnClick { Set-RecipeFavorite -RecipeId $rid -IsFavorite (-not $isFav) Sync-UDElement -Id "recipeCards" } } } } } } } } } } } } } |