Compare commits

..

No commits in common. "master" and "update/pokemon-card-view" have entirely different histories.

52 changed files with 641 additions and 1751 deletions

View File

@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Portfolio.Application.Services.Articles; using Portfolio.Application.Services.Articles;
using Portfolio.Application.Services.NWSWeatherService;
using Portfolio.Application.Services.PokemonNatureService; using Portfolio.Application.Services.PokemonNatureService;
using Portfolio.Application.Services.PokemonService; using Portfolio.Application.Services.PokemonService;
using Portfolio.Application.Services.PokemonSubskillService; using Portfolio.Application.Services.PokemonSubskillService;
@ -20,7 +19,6 @@ namespace Portfolio.Application
services.AddScoped<IPokemonService, PokemonService>(); services.AddScoped<IPokemonService, PokemonService>();
services.AddScoped<IPokemonSubskillService, PokemonSubskillService>(); services.AddScoped<IPokemonSubskillService, PokemonSubskillService>();
services.AddScoped<IPokemonNatureService, PokemonNatureService>(); services.AddScoped<IPokemonNatureService, PokemonNatureService>();
//services.AddScoped<INWSWeatherService, NWSWeatherService>();

View File

@ -1,17 +0,0 @@
using Portfolio.Domain.Features.TemperatureDay;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Application.Services.NWSWeatherService
{
public interface INWSWeatherService
{
Task<string> GetNearestStationAsync(double latitude, double longitude);
Task<double?> GetDailyAverageTempAsync(string stationId, DateTime date);
Task<List<TemperatureDay>> GetTemperatureDataAsync(double latitude, double longitude, int year);
}
}

View File

@ -1,123 +0,0 @@
using Portfolio.Domain.Features.TemperatureDay;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Portfolio.Application.Services.NWSWeatherService
{
public class NWSWeatherService : INWSWeatherService
{
private readonly HttpClient _httpClient;
public NWSWeatherService(HttpClient httpClient)
{
_httpClient = httpClient;
_httpClient.DefaultRequestHeaders.Add("User-Agent", "kira.jiroux@gmail.com"); // Replace with your email ideally
}
public async Task<string> GetNearestStationAsync(double latitude, double longitude)
{
var url = $"https://api.weather.gov/points/{latitude},{longitude}";
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
var json = await JsonDocument.ParseAsync(stream);
var stationUrl = json.RootElement
.GetProperty("properties")
.GetProperty("observationStations")
.GetString();
if (string.IsNullOrEmpty(stationUrl))
throw new Exception("Could not find station info.");
var stationListResponse = await _httpClient.GetAsync(stationUrl);
stationListResponse.EnsureSuccessStatusCode();
using var stationStream = await stationListResponse.Content.ReadAsStreamAsync();
var stationJson = await JsonDocument.ParseAsync(stationStream);
var firstStation = stationJson.RootElement
.GetProperty("features")[0]
.GetProperty("properties")
.GetProperty("stationIdentifier")
.GetString();
return firstStation;
}
public async Task<double?> GetDailyAverageTempAsync(string stationId, DateTime date)
{
var start = date.ToString("yyyy-MM-dd") + "T00:00:00Z";
var end = date.ToString("yyyy-MM-dd") + "T23:59:59Z";
var url = $"https://api.weather.gov/stations/{stationId}/observations?start={start}&end={end}";
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
using var stream = await response.Content.ReadAsStreamAsync();
var json = await JsonDocument.ParseAsync(stream);
var temps = new List<double>();
foreach (var feature in json.RootElement.GetProperty("features").EnumerateArray())
{
if (feature.TryGetProperty("properties", out var props) &&
props.TryGetProperty("temperature", out var tempObj) &&
tempObj.TryGetProperty("value", out var valueProp) &&
valueProp.ValueKind == JsonValueKind.Number)
{
var celsius = valueProp.GetDouble();
if (!double.IsNaN(celsius))
{
var fahrenheit = (celsius * 9.0 / 5.0) + 32.0;
temps.Add(fahrenheit);
}
}
}
if (temps.Count == 0)
return null;
return temps.Average();
}
public async Task<List<TemperatureDay>> GetTemperatureDataAsync(double latitude, double longitude, int year)
{
var stationId = await GetNearestStationAsync(latitude, longitude);
var result = new List<TemperatureDay>();
var startDate = new DateTime(year, 1, 1);
var endDate = new DateTime(year, 12, 31);
for (var date = startDate; date <= endDate; date = date.AddDays(1))
{
Console.WriteLine($"Fetching {date:yyyy-MM-dd}...");
var avgTemp = await GetDailyAverageTempAsync(stationId, date);
if (avgTemp.HasValue)
{
result.Add(new TemperatureDay
{
Date = date,
AvgTemp = Math.Round(avgTemp.Value, 1)
});
}
else
{
Console.WriteLine($"No data for {date:yyyy-MM-dd}");
}
await Task.Delay(600); // small delay to be nice to NWS
}
return result;
}
}
}

View File

@ -18,7 +18,6 @@ namespace Portfolio.Application.Services.PokemonSubskillService
} }
public async Task<List<PokemonSubskill>> GetAllPokemonSubskillsAsync() public async Task<List<PokemonSubskill>> GetAllPokemonSubskillsAsync()
{ {
Console.WriteLine("Does this fire every time");
return await _pokemonSubskillRepository.GetAllPokemonSubskillsAsync(); return await _pokemonSubskillRepository.GetAllPokemonSubskillsAsync();
} }
} }

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Domain.Features.TemperatureDay
{
public class TemperatureDay
{
public DateTime Date { get; set; }
public double AvgTemp { get; set; }
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Domain.Features.TemperatureRange
{
public class TemperatureRange
{
public double Min { get; set; }
public double Max { get; set; }
public string Color { get; set; } = "#ffffff";
}
}

View File

@ -2,7 +2,6 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Portfolio.Application.Services.Articles; using Portfolio.Application.Services.Articles;
using Portfolio.Application.Services.NWSWeatherService;
using Portfolio.Application.Services.PokemonService; using Portfolio.Application.Services.PokemonService;
using Portfolio.Domain.Features.Pokemon; using Portfolio.Domain.Features.Pokemon;
using Portfolio.Domain.Features.Pokemon_Natures; using Portfolio.Domain.Features.Pokemon_Natures;
@ -26,7 +25,6 @@ namespace Portfolio.Infrastructure
services.AddScoped<IPokemonRepository, PokemonRepository>(); services.AddScoped<IPokemonRepository, PokemonRepository>();
services.AddScoped<IPokemonNatureRepository, PokemonNatureRepository>(); services.AddScoped<IPokemonNatureRepository, PokemonNatureRepository>();
services.AddScoped<IPokemonSubskillRepository, PokemonSubskillRepository>(); services.AddScoped<IPokemonSubskillRepository, PokemonSubskillRepository>();
//services.AddScoped<INWSWeatherService, NWSWeatherService>();
return services; return services;
} }

View File

@ -13,10 +13,9 @@
<HeadOutlet /> <HeadOutlet />
</head> </head>
<body class="bg-primary-subtle"> <body>
<Routes /> <Routes />
<script src="_framework/blazor.web.js"></script> <script src="_framework/blazor.web.js"></script>
<script src="js/site.js"></script>
</body> </body>
</html> </html>

View File

@ -1,36 +0,0 @@
@attribute [StreamRendering]
@rendermode InteractiveServer
<div>
@if (TemperatureDays is null || TemperatureRanges is null)
{
<Loading />
}
else
{
<h3 class="text-xl font-bold mb-4">Temperature Blanket Visualizer</h3>
<div>
<div class="row">
<div class="col-10">
<div class="d-flex">
<div class="temperature-blanket">
@foreach (var day in TemperatureDays)
{
var color = GetColorForTemp(day.AvgTemp);
<div style="width: 6px; height: 600px; background-color:@color; margin-right: 1px;"
title="@day.Date.ToString("MMM dd") - @day.AvgTemp°F (@color)">
</div>
}
</div>
</div>
</div>
<div class="col">
<TemperatureRangeEditor TempRanges="@TemperatureRanges" OnRangesChanged="HandleRangesChanged" />
</div>
</div>
</div>
}
</div>

View File

@ -1,46 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.TemperatureDay;
using Portfolio.Domain.Features.TemperatureRange;
namespace Portfolio.WebUI.Server.Components.Component.Crochet_Components
{
public partial class TemperatureBlanketVisualizer : ComponentBase
{
[Parameter] public List<TemperatureDay> TemperatureDays { get; set; }
public List<TemperatureRange> TemperatureRanges { get; set; } = new();
protected override void OnInitialized()
{
TemperatureRanges = new()
{
new() { Min = 0, Max = 21, Color = "#ffffff" },
new() { Min = 21, Max = 28, Color = "#ffc0cb" },
new() { Min = 28, Max = 35, Color = "#dda0dd" },
new() { Min = 35, Max = 42, Color = "#add8e6" },
new() { Min = 42, Max = 49, Color = "#00008b" },
new() { Min = 49, Max = 56, Color = "#006400" },
new() { Min = 56, Max = 63, Color = "#07ed07" },
new() { Min = 63, Max = 70, Color = "#ffff00" },
new() { Min = 70, Max = 77, Color = "#ffa500" },
new() { Min = 77, Max = 84, Color = "#ff0000" },
new() { Min = 84, Max = 100, Color = "#000000" }
};
}
private string GetColorForTemp(double temp)
{
var range = TemperatureRanges.FirstOrDefault(r => temp >= r.Min && temp < r.Max);
return range?.Color ?? "#888888";
}
private void HandleRangesChanged(List<TemperatureRange> updatedRanges)
{
TemperatureRanges = updatedRanges;
StateHasChanged();
}
}
}

View File

@ -1,9 +0,0 @@
body {
}
.temperature-blanket {
display: flex;
overflow-x: auto;
background-color: black;
padding: 10px;
}

View File

@ -1,93 +0,0 @@
@using Microsoft.AspNetCore.Components.Web
@attribute [StreamRendering]
@rendermode InteractiveServer
<div class="container" > @* @onmouseup="OnMouseUp" @onmousemove="OnMouseMove" *@
<!-- Base number line -->
@* <div class="absolute top-1/2 left-0 right-0 h-1 bg-gray-300 transform -translate-y-1/2"></div> *@
@* <!-- Draggable nodes for adjusting range breakpoints -->
@for (int i = 0; i < TempRanges.Count; i++)
{
var left = i == 0 ? 0 : TempRanges[i - 1].Max;
var leftPercent = (left / 100.0) * 100;
<div class="absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-4 h-4 rounded-full bg-blue-600 cursor-pointer"
style="left: @leftPercent%"
@onmousedown="(e) => OnMouseDown(i, e)"
title="@left°F">
</div>
} *@
<!-- Color pickers for each range -->
<div class="card rounded-3">
<div class="card-header mb-3 text-center fw-bold">
Temperature Blanket Colors
</div>
@for (int i = 0; i < TempRanges.Count; i++)
{
var localIndex = i;
@* if (i == 0)
{
<div class="row align-items-center mb-2">
<div class="col-6 text-end pe-2">
<label class="form-label mb-0">
@TempRanges[i].Max&deg;
</label>
</div>
<div class="col-6 ps-2">
<input type="color"
value="@TempRanges[i].Color"
@onchange="e => HandleColorChange(e, localIndex)" />
</div>
</div>
}
else if (i == 10)
{
<div class="row align-items-center mb-2">
<div class="col-6 text-end pe-2">
<label class="form-label mb-0">
@TempRanges[i].Min&deg; +
</label>
</div>
<div class="col-6 ps-2">
<input type="color"
value="@TempRanges[i].Color"
@onchange="e => HandleColorChange(e, localIndex)" />
</div>
</div>
}
else
{
<div class="row align-items-center mb-2">
<div class="col-6 text-end pe-2">
<label class="form-label mb-0">
@TempRanges[i].Min&deg; @TempRanges[i].Max&deg;
</label>
</div>
<div class="col-6 ps-2">
<input type="color"
value="@TempRanges[i].Color"
@onchange="e => HandleColorChange(e, localIndex)" />
</div>
</div>
} *@
<div class="row align-items-center mb-2 ms-1">
<div class="col-6 text-end pe-2">
<label class="form-label mb-0">
@TempRanges[i].Min&deg; @TempRanges[i].Max&deg;
</label>
</div>
<div class="col-6 ps-2">
<input type="color"
value="@TempRanges[i].Color"
@onchange="e => HandleColorChange(e, localIndex)" />
</div>
</div>
}
</div>
</div>

View File

@ -1,88 +0,0 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Portfolio.Domain.Features.TemperatureRange;
namespace Portfolio.WebUI.Server.Components.Component.Crochet_Components
{
public partial class TemperatureRangeEditor : ComponentBase
{
[Parameter] public List<TemperatureRange> TempRanges { get; set; }
[Parameter] public EventCallback<List<TemperatureRange>> OnRangesChanged { get; set; }
[Inject] private IJSRuntime JS { get; set; }
private double windowWidth = 1000;
private int? draggingIndex = null;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
windowWidth = await JS.InvokeAsync<double>("eval", "window.innerWidth");
StateHasChanged();
}
}
private void OnMouseDown(int index, MouseEventArgs e)
{
draggingIndex = index;
}
private async void OnMouseUp()
{
if (draggingIndex != null)
{
draggingIndex = null;
await OnRangesChanged.InvokeAsync(TempRanges);
}
}
private void OnMouseMove(MouseEventArgs e)
{
if (draggingIndex is not int index || index <= 0 || index >= TempRanges.Count)
return;
var percent = (e.ClientX / windowWidth) * 100;
percent = Math.Clamp(percent, 0, 100);
var min = TempRanges[index - 1].Min;
var max = TempRanges[index].Max;
if (percent <= min + 1 || percent >= max - 1)
return;
TempRanges[index - 1].Max = percent;
TempRanges[index].Min = percent;
}
private void HandleColorChange(ChangeEventArgs e, int index)
{
if (index < 0 || index >= TempRanges.Count)
{
Console.WriteLine($"Color change requested for out-of-bounds index: {index}");
return;
}
var color = e?.Value?.ToString() ?? "#000000";
OnColorChanged(index, color);
}
private async void OnColorChanged(int index, string newColor)
{
//Console.WriteLine($"Color change at index {index} to {newColor}");
if (index >= 0 && index < TempRanges.Count)
{
TempRanges[index].Color = newColor;
Console.WriteLine($"Updated color: {TempRanges[index].Color}");
await OnRangesChanged.InvokeAsync(TempRanges);
}
else
{
Console.WriteLine($"Invalid index: {index} (Count: {TempRanges.Count})");
}
}
}
}

View File

@ -1,6 +0,0 @@
input[type="color"] {
width: 2.5rem;
height: 2rem;
padding: 0;
border: none;
}

View File

@ -25,38 +25,38 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
private List<PokemonImage> _shinyPokemonImages = new List<PokemonImage>(); private List<PokemonImage> _shinyPokemonImages = new List<PokemonImage>();
private Random random = new Random(); private Random random = new Random();
//protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
//{ {
// await LoadPokemonBackgrounds(); await LoadPokemonBackgrounds();
//} }
//private async Task LoadPokemonBackgrounds() private async Task LoadPokemonBackgrounds()
//{ {
// foreach (var pokemonimgurl in PokemonImages) foreach (var pokemonimgurl in PokemonImages)
// { {
// Console.WriteLine(pokemonimgurl); Console.WriteLine(pokemonimgurl);
// _pokemonImages.Add(new PokemonImage _pokemonImages.Add(new PokemonImage
// { {
// Url = pokemonimgurl, // URL retrieved from the database Url = pokemonimgurl, // URL retrieved from the database
// Left = random.Next(0, 100), Left = random.Next(0, 100),
// Top = random.Next(0, 100), Top = random.Next(0, 100),
// Size = random.Next(50, 130), Size = random.Next(50, 130),
// Rotation = random.Next(0, 360) Rotation = random.Next(0, 360)
// }); });
// } }
// foreach (var pokemonimgurl in ShinyPokemonImages) foreach (var pokemonimgurl in ShinyPokemonImages)
// { {
// _shinyPokemonImages.Add(new PokemonImage _shinyPokemonImages.Add(new PokemonImage
// { {
// Url = pokemonimgurl, // URL retrieved from the database Url = pokemonimgurl, // URL retrieved from the database
// Left = random.Next(0, 100), Left = random.Next(0, 100),
// Top = random.Next(0, 100), Top = random.Next(0, 100),
// Size = random.Next(50, 130), Size = random.Next(50, 130),
// Rotation = random.Next(0, 360) Rotation = random.Next(0, 360)
// }); });
// } }
//} }
} }

View File

@ -1 +0,0 @@
<div class="m-1 badge @_badgeitem.ToLower() border-0"><p class="statText">@_badgeitem</p></div>

View File

@ -1,22 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonBadge
{
[Parameter]
public string BadgeItem { get; set; }
private string _badgeitem { get; set; }
protected override void OnParametersSet()
{
if (BadgeItem != null)
{
_badgeitem = BadgeItem;
}
}
}
}

View File

@ -1,50 +0,0 @@
.badge {
display: flex;
align-items: center;
justify-content: center;
width: 90px;
height: 30px;
padding: 0.25rem;
border-radius: 30px;
color: white;
font-size: clamp(0.7rem, 1vw, 0.9rem);
text-align: center;
white-space: nowrap;
}
.statText {
margin: 0;
padding: 0;
width: 100%;
text-align: center;
}
/* Sleep Type Badge Styling */
.dozing {
background-color: #fcdc5e;
}
.snoozing {
background-color: #4ce8ed;
}
.slumbering {
background-color: #4588fb;
}
/* Speciality Badge Styling */
.berries {
background-color: #24d86b;
}
.ingredients {
background-color: #fdbe4d;
}
.skills {
background-color: #47a0fc;
}
.all {
background-color: #fc7992;
}

View File

@ -1,8 +1,7 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<div class="card-wrapper d-flex flex-column align-items-center"> <div class="mx-2 pokemon-card card-holo animated @GetTypeCssClass(_pokemon.PokemonType)">
<div class="pokemon-card card-holo animated @GetTypeCssClass(_pokemon.PokemonType)">
<!-- Pokemon Name, Number, and Type --> <!-- Pokemon Name, Number, and Type -->
<div class="z-3"> <div class="z-3">
@if (_pokemon.IsVariation) @if (_pokemon.IsVariation)
@ -33,7 +32,7 @@
<div class="z-3 pokemon-flavor-text @(GetTypeCssClass(_pokemon.PokemonType))"> <div class="z-3 pokemon-flavor-text @(GetTypeCssClass(_pokemon.PokemonType))">
@if (string.IsNullOrEmpty(_pokemon.FlavorText)) @if (string.IsNullOrEmpty(_pokemon.FlavorText))
{ {
<p class="fw-light">[ Pokemon Flavor Text Placeholder ]</p> <p class="">[ Pokemon Flavor Text Placeholder ]</p>
} }
else else
@ -44,16 +43,11 @@
</div> </div>
<!-- Pokemon Sleep Type and Specialty Badges --> <!-- Pokemon Sleep Type and Specialty Badges -->
<div class="position-absolute bottom-0 end-0 z-2"> <div class="position-absolute bottom-0 end-0 mb-1 me-1 z-2">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<PokemonBadge BadgeItem="@_pokemon.SleepType" /> <div class="m-1 badge @_pokemon.SleepType.ToLower() border-0"><p class="statText">@_pokemon.SleepType</p></div>
<PokemonBadge BadgeItem="@_pokemon.Speciality" /> <div class="m-1 badge @_pokemon.Speciality.ToLower() border-0"><p class="statText">@_pokemon.Speciality</p></div>
</div> </div>
</div> </div>
</div> </div>
<div class="mt-3">
<PokemonEditButton PokemonId="@_pokemon.Id" />
</div>
</div>

View File

@ -42,6 +42,5 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
return "pokemon-type-" + type.ToLower(); return "pokemon-type-" + type.ToLower();
} }
} }
} }

View File

@ -1,9 +1,9 @@
.pokemon-card { .pokemon-card {
position: relative; position: relative;
width: 100%; width: 24rem;
max-width: 350px; /* Prevent it from getting too huge */ height: 32rem;
aspect-ratio: 3 / 4; /* Maintains card shape dynamically */ max-width: 24rem;
overflow: hidden; max-height: 32rem;
background-color: var(--bg-color); background-color: var(--bg-color);
border-width: .5rem; border-width: .5rem;
border-style: solid; border-style: solid;
@ -20,37 +20,36 @@
transform: translateY(-13px); transform: translateY(-13px);
} }
.card-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.pokemon-name { .pokemon-name {
position: absolute; position: absolute;
top: 5%; top: 0 !important;
left: 3%; left: 0 !important;
margin-top: 1.5rem !important;
margin-left: 0.5rem !important;
transform: translateY(-50%) !important; transform: translateY(-50%) !important;
font-size: clamp(1.2rem, 2vw, 2rem); font-size: 2.5rem;
} }
.pokemon-number { .pokemon-number {
position: absolute; position: absolute;
top: 10%; top: 0 !important;
left: 6%; left: 0 !important;
margin-top: 3.3rem !important;
margin-left: 1.5rem !important;
transform: translateY(-50%) !important; transform: translateY(-50%) !important;
font-size: clamp(0.7rem, 1.2vw, 0.75rem); font-size: .75rem;
} }
.pokemon-type { .pokemon-type {
position: absolute; position: absolute;
top: 2%; top: 0 !important;
right: 2%; right: 0 !important;
width: clamp(1.5rem, 2.5vw, 2.5rem); width: 2.5rem;
height: clamp(1.5rem, 2.5vw, 2.5rem); height: 2.5rem;
margin-top: .5rem !important;
margin-right: .5rem !important;
} }
.pokemon-image { .pokemon-image {
@ -77,6 +76,7 @@
justify-content: center; /* Horizontally centers text */ justify-content: center; /* Horizontally centers text */
overflow: hidden; /* Ensures no scrollbar */ overflow: hidden; /* Ensures no scrollbar */
border-width: 2px; border-width: 2px;
border-radius: 5% / 13%; border-radius: 5% / 13%;
border-style: solid; border-style: solid;
@ -88,7 +88,7 @@
margin: 0; margin: 0;
width: 100%; width: 100%;
text-align: start; text-align: start;
font-size: min(12.5px, 1.5vw); /* Scales font but won't exceed 12.5px */ font-size: min(13px, 1.5vw); /* Scales font but won't exceed 13px */
line-height: 1.2; /* Adjust spacing for readability */ line-height: 1.2; /* Adjust spacing for readability */
white-space: normal; /* Ensures wrapping */ white-space: normal; /* Ensures wrapping */
word-wrap: break-word; word-wrap: break-word;
@ -102,10 +102,8 @@
transform: translate(-50%, -50%) !important; transform: translate(-50%, -50%) !important;
perspective: 1000px; perspective: 1000px;
display: inline-block; display: inline-block;
width: 80%; width: 20rem;
aspect-ratio: 1 / 1; height: 20rem;
max-width: 280px;
margin: 0 auto;
cursor: pointer; cursor: pointer;
} }
@ -135,8 +133,51 @@
transform: rotateY(180deg); transform: rotateY(180deg);
} }
.badge {
width: 90px;
height: 30px;
color: white;
padding: 4px 8px;
border-radius: 30px;
}
.statText {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: .8rem;
}
/* Sleep Type Badge Styling */
.dozing {
background-color: #fcdc5e;
}
.snoozing {
background-color: #4ce8ed;
}
.slumbering {
background-color: #4588fb;
}
/* Speciality Badge Styling */
.berries {
background-color: #24d86b;
}
.ingredients {
background-color: #fdbe4d;
}
.skills {
background-color: #47a0fc;
}
/* Type Card Styling */ /* Type Card Styling */
/* Type Themes - define vars only */
.pokemon-type-grass { .pokemon-type-grass {
--border-color: #45ca24; --border-color: #45ca24;
--bg-color: #e5f8dc; --bg-color: #e5f8dc;
@ -247,10 +288,7 @@
.card-holo { .card-holo {
position: relative; position: relative;
background-image: background-image: url("https://assets.codepen.io/13471/sparkles.gif"), url("https://assets.codepen.io/13471/holo.png"), linear-gradient(125deg, #ff008450 15%, #fca40040 30%, #ffff0030 40%, #00ff8a20 60%, #00cfff40 70%, #cc4cfa50 85% );
url("https://assets.codepen.io/13471/sparkles.gif"),
url("https://assets.codepen.io/13471/holo.png"),
linear-gradient(125deg, #ff008450 15%, #fca40040 30%, #ffff0030 40%, #00ff8a20 60%, #00cfff40 70%, #cc4cfa50 85% );
background-blend-mode: screen; background-blend-mode: screen;
background-size: cover; background-size: cover;
background-position: center; background-position: center;

View File

@ -13,7 +13,7 @@
<!-- Home --> <!-- Home -->
<button class="btn btn-primary mx-1 align-content-center" style="border-radius: 50px 15px; max-width: 60px;"> <button class="btn btn-primary mx-1 align-content-center" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemonsleep"> <NavLink href="/pokemonsleep">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" class="bi bi-house-fill mb-1" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-fill" viewBox="0 0 16 16">
<path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L8 2.207l6.646 6.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293z" /> <path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L8 2.207l6.646 6.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293z" />
<path d="m8 3.293 6 6V13.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 13.5V9.293z" /> <path d="m8 3.293 6 6V13.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 13.5V9.293z" />
</svg> </svg>
@ -23,7 +23,7 @@
<!-- Pokemon Table--> <!-- Pokemon Table-->
<button class="btn btn-info mx-1" style="border-radius: 50px 15px; max-width: 60px;"> <button class="btn btn-info mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemon"> <NavLink href="/pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" class="bi bi-table mb-1" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-table" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm15 2h-4v3h4zm0 4h-4v3h4zm0 4h-4v3h3a1 1 0 0 0 1-1zm-5 3v-3H6v3zm-5 0v-3H1v2a1 1 0 0 0 1 1zm-4-4h4V8H1zm0-4h4V4H1zm5-3v3h4V4zm4 4H6v3h4z" /> <path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm15 2h-4v3h4zm0 4h-4v3h4zm0 4h-4v3h3a1 1 0 0 0 1-1zm-5 3v-3H6v3zm-5 0v-3H1v2a1 1 0 0 0 1 1zm-4-4h4V8H1zm0-4h4V4H1zm5-3v3h4V4zm4 4H6v3h4z" />
</svg> </svg>
</NavLink> </NavLink>
@ -31,8 +31,8 @@
<!-- Rate Pokemon --> <!-- Rate Pokemon -->
<button class="btn btn-success mx-1" style="border-radius: 50px 15px; max-width: 60px;"> <button class="btn btn-success mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/rate-pokemon"> <NavLink href="/pokemonsleep/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" class="bi bi-award-fill mb-1" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-award-fill" viewBox="0 0 16 16">
<path d="m8 0 1.669.864 1.858.282.842 1.68 1.337 1.32L13.4 6l.306 1.854-1.337 1.32-.842 1.68-1.858.282L8 12l-1.669-.864-1.858-.282-.842-1.68-1.337-1.32L2.6 6l-.306-1.854 1.337-1.32.842-1.68L6.331.864z" /> <path d="m8 0 1.669.864 1.858.282.842 1.68 1.337 1.32L13.4 6l.306 1.854-1.337 1.32-.842 1.68-1.858.282L8 12l-1.669-.864-1.858-.282-.842-1.68-1.337-1.32L2.6 6l-.306-1.854 1.337-1.32.842-1.68L6.331.864z" />
<path d="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" /> <path d="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" />
</svg> </svg>
@ -42,7 +42,7 @@
<!-- Add Pokemon (Wrap in Auth) --> <!-- Add Pokemon (Wrap in Auth) -->
<button class="btn btn-warning mx-1" style="border-radius: 50px 15px; max-width: 60px;"> <button class="btn btn-warning mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemonsleep/add-new-pokemon"> <NavLink href="/pokemonsleep/add-new-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" class="bi bi-plus-circle-fill mb-1" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8.5 4.5a.5.5 0 0 0-1 0v3h-3a.5.5 0 0 0 0 1h3v3a.5.5 0 0 0 1 0v-3h3a.5.5 0 0 0 0-1h-3z" /> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8.5 4.5a.5.5 0 0 0-1 0v3h-3a.5.5 0 0 0 0 1h3v3a.5.5 0 0 0 1 0v-3h3a.5.5 0 0 0 0-1h-3z" />
</svg> </svg>
</NavLink> </NavLink>

View File

@ -1,135 +0,0 @@
<div class="pokemon-rating-panel">
<!-- Dropdown Selects -->
<div class="ratings bg-light-subtle col">
<h3 class="mb-3 row">Select Nature & Subskills</h3>
<!-- Nature -->
<div class="d-flex justify-content-between align-items-center row">
<div class="col">
<label>Select Nature</label>
<select class="form-control" @bind="SelectedNatureId">
<option value="" disabled selected >Choose Nature...</option>
@foreach (var nature in NatureList)
{
<option value="@nature.Id">@nature.Nature</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">@lastnaturescore</span>
</h4>
</div>
</div>
<!-- Subskill 1 -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<div class="col">
<label for="subskillSelect1">Select Level 10 Subskill</label>
<select id="subskillSelect1" class="form-control" @bind="Subskill1">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">@lastS1score</span>
</h4>
</div>
</div>
<!-- Subskill 2 -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<div class="col">
<label for="subskillSelect2">Select Level 25 Subskill</label>
<select id="subskillSelect2" class="form-control" @bind="Subskill2">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">@lastS2score</span>
</h4>
</div>
</div>
<!-- Subskill 3 -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<div class="col">
<label for="subskillSelect3">Select Level 50 Subskill</label>
<select id="subskillSelect3" class="form-control" @bind="Subskill3">
<option value="" selected disabled>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">@lastS3score</span>
</h4>
</div>
</div>
<!-- Subskill 4 Disabled -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<div class="col">
<label for="subskillSelect4">Select Level 75 Subskill</label>
<select id="subskillSelect4" disabled class="form-control" @bind="Subskill4">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">0</span>
</h4>
</div>
</div>
<!-- Subskill 5 Disabled -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<div class="col">
<label for="subskillSelect5">Select Level 100 Subskill</label>
<select id="subskillSelect5" disabled class="form-control mb-2" @bind="Subskill5">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
<div class="text-center col">
<h4 class="mt-4">
<span class="text-muted">0</span>
</h4>
</div>
</div>
<hr/>
<!-- Score Output -->
<div class="d-flex justify-content-between align-items-center mt-3 row">
<h3 class="col">Final Score:</h3>
<div class="p-2 rounded text-center col"
style="background-color:@ScoreBackgroundColor; color:@ScoreColor; ">
<h3>@FinalScore</h3>
</div>
</div>
</div>
</div>

View File

@ -1,156 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.Pokemon;
using Portfolio.Domain.Features.Pokemon_Natures;
using Portfolio.Domain.Features.Pokemon_Subskills;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
partial class PokemonRatingPanel
{
[Parameter] public Pokemon PokemonToRate { get; set; }
[Parameter] public List<PokemonNature> NatureList { get; set; } = new();
[Parameter] public List<PokemonSubskill> SubskillList { get; set; } = new();
private int SelectedNatureId;
private int Subskill1;
private int Subskill2;
private int Subskill3;
private int Subskill4;
private int Subskill5;
private int FinalScore;
private string ScoreBackgroundColor = "#FFFFFF";
private string ScoreColor = "#000000";
private int lastNatureId;
private int lastS1, lastS2, lastS3;
private int lastnaturescore, lastS1score, lastS2score, lastS3score;
protected override void OnAfterRender(bool firstRender)
{
// If last Nature or Subskill is different than previous
if (PokemonToRate != null) {
if (SelectedNatureId != lastNatureId)
{
lastNatureId = SelectedNatureId;
var nature = NatureList.FirstOrDefault(n => n.Id == lastNatureId);
lastnaturescore = PokemonToRate.Speciality switch
{
"Berries" => nature.BerryRating,
"Ingredients" => nature.IngredientRating,
"Skills" => nature.SkillRating,
_ => 0
};
}
if (Subskill1 != lastS1)
{
lastS1 = Subskill1;
var s1 = SubskillList.FirstOrDefault(s => s.Id == Subskill1);
lastS1score = PokemonToRate.Speciality switch
{
"Berries" => s1.BerryRank,
"Ingredients" => s1.IngredientRank,
"Skills" => s1.SkillRank,
_ => 0
};
}
if (Subskill2 != lastS2)
{
lastS2 = Subskill2;
var s2 = SubskillList.FirstOrDefault(s => s.Id == Subskill2);
lastS2score = PokemonToRate.Speciality switch
{
"Berries" => s2.BerryRank,
"Ingredients" => s2.IngredientRank,
"Skills" => s2.SkillRank,
_ => 0
};
}
if (Subskill3 != lastS3)
{
lastS3 = Subskill3;
var s3 = SubskillList.FirstOrDefault(s => s.Id == Subskill3);
lastS3score = PokemonToRate.Speciality switch
{
"Berries" => s3.BerryRank,
"Ingredients" => s3.IngredientRank,
"Skills" => s3.SkillRank,
_ => 0
};
}
}
CalculateScore();
StateHasChanged();
}
private void CalculateScore()
{
if (PokemonToRate == null || SelectedNatureId == 0 || lastS1 == 0 || lastS2 == 0 || lastS3 == 0)
{
FinalScore = 0;
ScoreBackgroundColor = "#FFFFFF";
ScoreColor = "#000000";
return;
}
var nature = NatureList.FirstOrDefault(n => n.Id == SelectedNatureId);
var s1 = SubskillList.FirstOrDefault(s => s.Id == Subskill1);
var s2 = SubskillList.FirstOrDefault(s => s.Id == Subskill2);
var s3 = SubskillList.FirstOrDefault(s => s.Id == Subskill3);
if (nature == null || s1 == null || s2 == null || s3 == null)
{
FinalScore = 0;
ScoreBackgroundColor = "#FFFFFF";
ScoreColor = "#000000";
return;
}
FinalScore = PokemonToRate.Speciality switch
{
"Berries" => nature.BerryRating + s1.BerryRank + s2.BerryRank + s3.BerryRank,
"Ingredients" => nature.IngredientRating + s1.IngredientRank + s2.IngredientRank + s3.IngredientRank,
"Skills" => nature.SkillRating + s1.SkillRank + s2.SkillRank + s3.SkillRank,
_ => 0
};
// Set score background based on value
ScoreBackgroundColor = FinalScore switch
{
8 => "#16C47F",
7 => "#33CB8F",
6 => "#50D39F",
5 => "#6DDAAF",
4 => "#8BE2BF",
3 => "#A8E9CF",
2 => "#C5F0DF",
1 => "#E2F8EF",
0 => "#FFFFFF",
-1 => "#FFE7E7",
-2 => "#FED0D0",
-3 => "#FEB8B8",
-4 => "#FDA0A0",
-5 => "#FD8888",
-6 => "#FC7171",
-7 => "#FC5959",
-8 => "#FB4141",
_ => "#FFFFFF"
};
ScoreColor = FinalScore == 0 ? "#000000" : "#FFFFFF";
}
}
}

View File

@ -1,49 +0,0 @@
.pokemon-rating-panel {
display: flex;
flex-direction: column;
gap: 1.5rem;
width: 100%;
height: 70vh;
}
.ratings {
flex: 2;
padding: 1.5rem;
border-radius: 5% / 3.5%;
}
.select-width {
width: 16rem;
}
.score-width {
width: 6rem;
}
@media (max-width: 768px) {
.pokemon-rating-panel {
padding: 1rem;
}
.ratings {
padding: 1rem;
}
.d-flex.justify-content-between.align-items-center {
flex-direction: column;
align-items: stretch !important;
gap: 0.5rem;
}
.select-width
{
width: 4rem;
text-align: center;
}
.score-width h4 {
margin-top: 0.5rem !important;
}
}

View File

@ -1,27 +0,0 @@

<!-- Search Input -->
<div class="pokemon-selector p-3 bg-light">
<input class="form-control mb-3" placeholder="Search Pokémon..." @bind="SearchTerm" @oninput="HandleSearch" />
<!-- Scrollable Pokémon Grid -->
<div class="row pokemon-grid">
@foreach (var pokemon in FilteredPokemon)
{
bool isSelected = SelectedPokemon?.Id == pokemon.Id;
<div class="col-6 col-md-3 mb-3">
<div class="card pokemon-card small-card @(isSelected ? "border-primary border-2 shadow" : "border-2 border-white")"
@onclick="() => SelectPokemon(pokemon)">
<img src="@pokemon.PokemonImageUrl" class="card-img-top" style="height: 50px; object-fit: contain;" />
<div class="card-body p-2 text-center">
<small>@pokemon.PokemonId</small>
</div>
</div>
</div>
}
</div>
</div>
<style>
</style>

View File

@ -1,37 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
partial class PokemonSelector
{
[Parameter]
public List<Pokemon> PokemonList { get; set; } = new();
[Parameter]
public Pokemon? SelectedPokemon { get; set; }
[Parameter]
public EventCallback<Pokemon> OnPokemonSelected { get; set; }
private string SearchTerm { get; set; } = string.Empty;
private List<Pokemon> FilteredPokemon =>
string.IsNullOrWhiteSpace(SearchTerm)
? PokemonList
: PokemonList.Where(p =>
p.PokemonName.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase)).ToList();
private async Task HandleSearch(ChangeEventArgs e)
{
SearchTerm = e?.Value?.ToString() ?? "";
}
private async Task SelectPokemon(Pokemon pokemon)
{
await OnPokemonSelected.InvokeAsync(pokemon);
}
}
}

View File

@ -1,31 +0,0 @@
.pokemon-selector {
height: 70vh;
width: 20vw;
border: 1px solid #ccc;
border-radius: 5% / 3.5%;
display: flex;
flex-direction: column;
}
.pokemon-grid {
flex: 1 1 auto;
overflow-y: auto;
}
.pokemon-card {
cursor: pointer;
transition: transform 0.15s ease-in-out;
}
.pokemon-card:hover {
transform: scale(1.05);
}
.small-card {
font-size: 0.75rem;
}

View File

@ -5,38 +5,36 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<!-- Table A: Desktop View-->
<div class="container d-none d-md-block " style="height: 70vh;">
<!-- Main UI --> <!-- Main UI -->
<div class="card shadow-sm border-0 mt-4 mx-auto col-12 col-md-10 col-lg-8 pokemontable"> <div class="card shadow border-0 mt-4 m-auto w-50">
<!-- Table Header --> <!-- Table Header -->
<div class="row card-header bg-secondary bg-gradient py-3 border-0"> <div class="card-header bg-secondary bg-gradient ml-0 py-3 border-0">
<div class="flex-row justify-content-between"> <div class="row">
<div class="text-center position-relative"> <div class="text-center position-relative">
<input class="form-control position-absolute top-0 start-0 border-0 w-25" placeholder="Search Pokémon..." @bind="SearchTerm" @oninput="HandleSearch" />
<h2 class="text-info text-decoration-underline">Available Pokémon</h2> <h2 class="text-info text-decoration-underline">Available Pokémon</h2>
<div class="m-1 badge bg-info position-absolute top-0 end-0 border-0"><p class="statText">@(pokemons.Count()) Pokémon</p></div> <div class="m-1 badge bg-info position-absolute top-0 end-0 border-0"><p class="statText">@(pokemons.Count()) Pokemon</p></div>
</div> </div>
</div> </div>
</div> </div>
<!-- Table -->
<div class="tableFixHead">
<table class="table table-borderless border-0 table-secondary table-striped align-middle">
<div class="tableFixHead d-flex flex-column justify-content-start bg-secondary table-responsive row">
<table class="table col table-borderless border-0 table-secondary table-striped align-middle">
<!-- Table Head --> <!-- Table Head -->
<thead class=""> <thead class="">
<tr class=""> <tr class="">
<th class="text-white text-bg-info col-2 d-none d-md-table-cell" scope="col"></th> <th class="text-white text-bg-info col-2" scope="col"></th>
<th class="text-white text-bg-info col-1" scope="col">#</th> <th class="text-white text-bg-info col-1" scope="col">#</th>
<th class="text-white text-bg-info col-2" scope="col">Pokémon</th> <th class="text-white text-bg-info col-2" scope="col">Pokemon</th>
<th class="text-white text-bg-info col-1 text-center" scope="col">Type</th> <th class="text-white text-bg-info col-1 text-center" scope="col">Type</th>
<th class="text-white text-bg-info col-2 text-center" scope="col">Sleep Type</th> <th class="text-white text-bg-info col-2 text-center" scope="col">Sleep Type</th>
<th class="text-white text-bg-info col-2 text-center" scope="col">Speciality</th> <th class="text-white text-bg-info col-2 text-center" scope="col">Speciality</th>
<!-- <th class="text-bg-info text-end" scope="col">Control Buttons</th> -->
</tr> </tr>
</thead> </thead>
<!-- If/Else Pokemon Loaded-->
@if(pokemons == null) @if(pokemons == null)
{ {
<tbody> <tbody>
@ -46,25 +44,22 @@
else else
{ {
<!-- Table Body --> <!-- Table Body -->
<tbody class=""> <tbody >
<tr></tr> @foreach (var pokemon in pokemons)
@if (FilteredPokemon != null && FilteredPokemon.Any())
{ {
<tr class="">
@foreach (var pokemon in FilteredPokemon)
{
<tr class="flex-row">
<!-- Section: Pokemon Image --> <!-- Section: Pokemon Image -->
@{ @{
string baseUrl = pokemon.PokemonImageUrl; string baseUrl = pokemon.PokemonImageUrl;
string shinyUrl = pokemon.PokemonShinyImageUrl; string shinyUrl = pokemon.PokemonShinyImageUrl;
} }
<td class="text-center d-none d-md-table-cell"> <td style="text-align: center;">
@if (shinyUrl == null) @if (shinyUrl == null)
{ {
<div class="flip-container"> <div class="flip-container">
<div class="flipper"> <div class="flipper">
<img class="front img-fluid" style="max-width: 100px;" src="@baseUrl" /> <img class="front" src="@baseUrl" />
</div> </div>
</div> </div>
@ -73,8 +68,8 @@
{ {
<div class="flip-container" @onclick="() => ToggleImage(pokemon.Id)"> <div class="flip-container" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper @(isShiny[pokemon.Id] ? "flipped" : "")"> <div class="flipper @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" style="max-width: 100px;" src="@baseUrl" /> <img class="front" src="@baseUrl" />
<img class="back img-fluid" style="max-width: 100px;" src="@shinyUrl" /> <img class="back" src="@shinyUrl" />
</div> </div>
</div> </div>
@ -82,48 +77,61 @@
</td> </td>
<!-- Section 2: Pokemon # --> <!-- Section 2: Pokemon # -->
<th class="" scope="row" style="cursor: default;">@pokemon.PokemonId</th> <th scope="row" style="cursor: default;">@pokemon.PokemonId</th>
<!-- Section 3: Pokemon Name --> <!-- Section 3: Pokemon Name -->
@if (pokemon.IsVariation) // If a Variant
<td @onclick="() => ViewPokemon(pokemon.PokemonId)" class="pokemon-name-style fw-light col-2">@(pokemon.IsVariation && ToggleVariationName(pokemon.Id, pokemon.PokemonId) ? $"{pokemon.VariationName} {pokemon.PokemonName}" : pokemon.PokemonName)</td> {
@if (pokemon.VariationName == "Alolan")
{
<td @onclick="() => ViewPokemon(pokemon.PokemonId)" class="pokemon-name-style"> Alolan @pokemon.PokemonName</td>
}
@if (pokemon.VariationName == "Paldean")
{
<td @onclick="() => ViewPokemon(pokemon.PokemonId)" class="pokemon-name-style"> Paldean @pokemon.PokemonName</td>
}
}
else // Otherwise, Base Case
{
<td @onclick="() => ViewPokemon(pokemon.PokemonId)" class="pokemon-name-style"> @pokemon.PokemonName</td>
}
<!-- Section 4: Pokemon Type --> <!-- Section 4: Pokemon Type -->
<td class=""> <td>
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:36px; height:36px;" /> <img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:36px; height:36px;" />
</div> </div>
</td> </td>
<!-- Section 5: Sleep Type --> <!-- Section 5: Sleep Type -->
<td class="" style=""> <td style="">
<div class="d-flex justify-content-center "> <div class="d-flex justify-content-center ">
<PokemonBadge BadgeItem="@pokemon.SleepType" /> <div class=" badge @pokemon.SleepType.ToLower() border-0"><p class="statText">@pokemon.SleepType</p></div>
</div> </div>
</td> </td>
<!-- Section 6: Speciality --> <!-- Section 6: Speciality -->
<td class="" style=""> <td style="">
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<PokemonBadge BadgeItem="@pokemon.Speciality" /> <div class=" badge @pokemon.Speciality.ToLower() border-0"><p class="statText">@pokemon.Speciality</p></div>
</div> </div>
</td> </td>
</tr> <!-- Section 7: Functional Buttons -->
} <!--
} <td>
else <div class="d-flex justify-content-end">
{ <PokemonEditButton PokemonId="pokemon.Id" />
<tr> <button class="btn btn-danger rounded rounded-5 mx-1" @onclick="() => ConfirmDelete(pokemon.Id)">
<td colspan="100%"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3-fill" viewBox="0 0 16 16">
<div class="d-flex justify-content-center align-items-center" style="height: 200px;"> <path d="M11 1.5v1h3.5a.5.5 0 0 1 0 1h-.538l-.853 10.66A2 2 0 0 1 11.115 16h-6.23a2 2 0 0 1-1.994-1.84L2.038 3.5H1.5a.5.5 0 0 1 0-1H5v-1A1.5 1.5 0 0 1 6.5 0h3A1.5 1.5 0 0 1 11 1.5m-5 0v1h4v-1a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5M4.5 5.029l.5 8.5a.5.5 0 1 0 .998-.06l-.5-8.5a.5.5 0 1 0-.998.06m6.53-.528a.5.5 0 0 0-.528.47l-.5 8.5a.5.5 0 0 0 .998.058l.5-8.5a.5.5 0 0 0-.47-.528M8 4.5a.5.5 0 0 0-.5.5v8.5a.5.5 0 0 0 1 0V5a.5.5 0 0 0-.5-.5" />
<p class="text-muted">Pokémon could not be found.</p> </svg>
</button>
</div> </div>
</td> </td>
-->
</tr> </tr>
} }
</tbody> </tbody>
@ -132,75 +140,6 @@
</table> </table>
</div> </div>
</div> </div>
</div>
<!-- Desktop B: Mobile View -->
<div class="container card border-0 d-block d-md-none mx-auto mt-4 shadow-sm">
<!-- Table Header -->
<div class="row card-header bg-secondary bg-gradient ml-0 py-3 border-0 bg-info">
<div class="flex-row justify-content-between">
<div class="text-center position-relative">
<h2 class="text-white text-decoration-underline">Pokémon</h2>
<div class="m-1 badge bg-white text-info position-absolute top-0 end-0 border-0 w-auto"><p class="statText">@(pokemons.Count()) Pokémon</p></div>
</div>
</div>
</div>
<!-- Table Body -->
<div class="tableFixHead row">
<table class="table table-striped border-0">
<tbody>
@if (pokemons == null)
{
<Loading />
}
else
{
@foreach (var pokemon in pokemons)
{
<tr class="border-0">
<div class="d-flex align-items-center">
<!-- Pokemon Image -->
<div class="me-3">
<div class="flip-container-sm" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper-sm @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" src="@pokemon.PokemonImageUrl" />
@if (pokemon.PokemonShinyImageUrl != null)
{
<img class="back img-fluid" src="@pokemon.PokemonShinyImageUrl" />
}
</div>
</div>
</div>
<div class="">
<!-- Number and Name -->
<h5>
@pokemon.PokemonId -
<span class="pokemon-name-style fw-light" @onclick="() => ViewPokemon(pokemon.PokemonId)">
@(pokemon.IsVariation && ToggleVariationName(pokemon.Id, pokemon.PokemonId) ? $"{pokemon.VariationName} {pokemon.PokemonName}" : pokemon.PokemonName)
</span>
</h5>
<!-- Stats -->
<div class="d-flex flex-wrap align-items-center gap-2">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:28px;" />
<PokemonBadge BadgeItem="@pokemon.SleepType" />
<PokemonBadge BadgeItem="@pokemon.Speciality" />
</div>
</div>
</div>
</tr>
}
}
</tbody>
</table>
</div>
</div>

View File

@ -25,18 +25,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
} }
} }
} }
private string SearchTerm { get; set; } = string.Empty;
private List<Pokemon> FilteredPokemon =>
string.IsNullOrWhiteSpace(SearchTerm)
? AllPokemon
: AllPokemon.Where(p =>
p.PokemonName.Contains(SearchTerm, StringComparison.OrdinalIgnoreCase)).ToList();
private async Task HandleSearch(ChangeEventArgs e)
{
SearchTerm = e?.Value?.ToString() ?? "";
}
private void ToggleImage(int Id) private void ToggleImage(int Id)
{ {
if (isShiny.ContainsKey(Id)) if (isShiny.ContainsKey(Id))
@ -45,18 +34,6 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
} }
} }
private bool ToggleVariationName(int Id, int PokemonId)
{
foreach (var pokemon in pokemons)
{
if (pokemon.PokemonId == PokemonId && pokemon.Id != Id)
{
return true;
}
}
return false;
}
private async Task ConfirmDelete(int Id) private async Task ConfirmDelete(int Id)
{ {
bool confirm = await JS.InvokeAsync<bool>("confirm", "Are you sure you want to delete this Pokémon?"); bool confirm = await JS.InvokeAsync<bool>("confirm", "Are you sure you want to delete this Pokémon?");

View File

@ -5,10 +5,6 @@
width: 10%; width: 10%;
} }
.pokemontable {
height: 69vh;
}
.tableFixHead { .tableFixHead {
overflow: auto; overflow: auto;
height: 600px; height: 600px;
@ -20,13 +16,8 @@
z-index: 10; z-index: 10;
} }
.align-top-tbody {
vertical-align: top;
}
.pokemon-name-style { .pokemon-name-style {
cursor:pointer; cursor:pointer;
font-size: 1.3rem;
} }
@ -50,43 +41,6 @@
transform: rotateY(180deg); transform: rotateY(180deg);
} }
.flip-container-sm {
perspective: 1000px;
width: 64px;
height: 64px;
}
.flipper-sm {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
.flipper-sm img {
backface-visibility: hidden;
position: absolute;
width: 64px;
height: 64px;
}
.flipper-sm .front {
z-index: 2;
}
.flipper-sm .back {
transform: rotateY(180deg);
}
.flipper-sm.flipped {
transform: rotateY(180deg);
}
.fixed-row-height {
height: 90px; /* or any height that suits your card style */
}
.pokeimage { .pokeimage {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -129,5 +83,28 @@
cursor: default; cursor: default;
} }
.dozing {
background-color: #fcdc5e;
}
.snoozing {
background-color: #4ce8ed;
}
.slumbering {
background-color: #4588fb;
}
.berries {
background-color: #24d86b;
}
.ingredients {
background-color: #fdbe4d;
}
.skills {
background-color: #47a0fc;
}

View File

@ -1,11 +0,0 @@
<div class="position-absolute bottom-0 vw-100">
<footer class="d-flex flex-column align-content-center">
<hr class="border-bottom border-primary border-1 mx-5">
<p class="text-center text-primary">
Made with Love
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-through-heart" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l.53-.53c-.771-.802-1.328-1.58-1.704-2.32-.798-1.575-.775-2.996-.213-4.092C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182a22 22 0 0 1-2.685-2.062l-.539.54V14a.5.5 0 0 1-.146.354zm2.893-4.894A20.4 20.4 0 0 0 8 12.71c2.456-1.666 3.827-3.207 4.489-4.512.679-1.34.607-2.42.215-3.185-.817-1.595-3.087-2.054-4.346-.761L8 4.62l-.358-.368c-1.259-1.293-3.53-.834-4.346.761-.392.766-.464 1.845.215 3.185.323.636.815 1.33 1.519 2.065l1.866-1.867a.5.5 0 1 1 .708.708z" />
</svg>
</p>
</footer>
</div>

View File

@ -1,13 +1,12 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<div class="page bg-primary-subtle h-100"> <div class="page" >
<main class="h-100 w-100">
<NavMenu3 /> <Sidebar/>
<article class="container m-auto">
<div class=""> <main class="bg-primary-subtle">
<article class="content px-4">
@Body @Body
</div>
</article> </article>
</main> </main>
@* <MadeWithLoveFooter/> *@
</div> </div>

View File

@ -1,35 +1,45 @@
<div class="navbar navbar-expand bg-primary border-0"> <div class="navbar navbar-expand-lg navbar-light bg-info justify-content-md-center" id="navbarsExample08">
<div class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-light text-decoration-none px-2">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#FFFFFF" class="bi bi-arrow-through-heart" viewBox="0 0 16 16" style="cursor: pointer;">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l.53-.53c-.771-.802-1.328-1.58-1.704-2.32-.798-1.575-.775-2.996-.213-4.092C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182a22 22 0 0 1-2.685-2.062l-.539.54V14a.5.5 0 0 1-.146.354zm2.893-4.894A20.4 20.4 0 0 0 8 12.71c2.456-1.666 3.827-3.207 4.489-4.512.679-1.34.607-2.42.215-3.185-.817-1.595-3.087-2.054-4.346-.761L8 4.62l-.358-.368c-1.259-1.293-3.53-.834-4.346.761-.392.766-.464 1.845.215 3.185.323.636.815 1.33 1.519 2.065l1.866-1.867a.5.5 0 1 1 .708.708z" />
</svg>
<span class="fs-4 mx-1 text-white">Kira Jiroux</span>
</div>
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> <li class="nav-item">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-heart-fill mb-1" viewBox="0 0 16 16"> <span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Kira Jiroux
<path d="M7.293 1.5a1 1 0 0 1 1.414 0L11 3.793V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v3.293l2.354 2.353a.5.5 0 0 1-.708.707L8 2.207 1.354 8.853a.5.5 0 1 1-.708-.707z" />
<path d="m14 9.293-6-6-6 6V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5zm-6-.811c1.664-1.673 5.825 1.254 0 5.018-5.825-3.764-1.664-6.691 0-5.018" />
</svg> <span class="mx-2 mt-0">Home</span>
</NavLink> </NavLink>
</li> </li>
<li> <li class="nav-item">
<NavLink class="nav-link" href="temperature-blanket"> <NavLink class="nav-link" href="articles">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-border-outer" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-journal-richtext" viewBox="0 0 16 16">
<path d="M7.5 1.906v.938h1v-.938zm0 1.875v.938h1V3.78h-1zm0 1.875v.938h1v-.938zM1.906 8.5h.938v-1h-.938zm1.875 0h.938v-1H3.78v1zm1.875 0h.938v-1h-.938zm2.813 0v-.031H8.5V7.53h-.031V7.5H7.53v.031H7.5v.938h.031V8.5zm.937 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zM7.5 9.406v.938h1v-.938zm0 1.875v.938h1v-.938zm0 1.875v.938h1v-.938z" /> <path d="M7.5 3.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m-.861 1.542 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047L11 4.75V7a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 7v-.5s1.54-1.274 1.639-1.208M5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5m0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5" />
<path d="M0 0v16h16V0zm1 1h14v14H1z" /> <path d="M3 0h10a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-1h1v1a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v1H1V2a2 2 0 0 1 2-2" />
</svg><span class="mx-2 mt-0">Crochet</span> <path d="M1 5v-.5a.5.5 0 0 1 1 0V5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0V8h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zm0 3v-.5a.5.5 0 0 1 1 0v.5h.5a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z" />
</svg> Articles
</NavLink> </NavLink>
</li> </li>
<li> <li class="nav-item">
<NavLink class="nav-link" href="pokemonsleep"> <NavLink class="nav-link" href="pokemonsleep">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.5 4.002V12h1.283V9.164h1.668C10.033 9.164 11 8.08 11 6.586c0-1.482-.955-2.584-2.538-2.584zm2.77 4.072c.893 0 1.419-.545 1.419-1.488s-.526-1.482-1.42-1.482H6.778v2.97z" /> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.5 4.002V12h1.283V9.164h1.668C10.033 9.164 11 8.08 11 6.586c0-1.482-.955-2.584-2.538-2.584zm2.77 4.072c.893 0 1.419-.545 1.419-1.488s-.526-1.482-1.42-1.482H6.778v2.97z" />
</svg> <span class="mx-2 mt-0">Pokémon Sleep</span> </svg> Pokemon Sleep
</NavLink> </NavLink>
</li> </li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdown08" data-bs-toggle="dropdown" aria-expanded="false">Pokemon Sleep</a>
<ul class="dropdown-menu" aria-labelledby="dropdown08">
<li>
<NavLink class="nav-link" href="pokemonsleep/add-new-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.5 4.002V12h1.283V9.164h1.668C10.033 9.164 11 8.08 11 6.586c0-1.482-.955-2.584-2.538-2.584zm2.77 4.072c.893 0 1.419-.545 1.419-1.488s-.526-1.482-1.42-1.482H6.778v2.97z" />
</svg> Pokemon Sleep
</NavLink>
</li>
<li>
<NavLink class="nav-link" href="pokemonsleep/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0M5.5 4.002V12h1.283V9.164h1.668C10.033 9.164 11 8.08 11 6.586c0-1.482-.955-2.584-2.538-2.584zm2.77 4.072c.893 0 1.419-.545 1.419-1.488s-.526-1.482-1.42-1.482H6.778v2.97z" />
</svg> Pokemon Sleep
</NavLink>
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
</ul> </ul>
</div> </div>

View File

@ -26,14 +26,6 @@
</svg> <span class="mx-2 mt-0">Articles</span> </svg> <span class="mx-2 mt-0">Articles</span>
</NavLink> </NavLink>
</li> </li>
<li>
<NavLink class="nav-link" href="temperature-blanket">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-border-outer" viewBox="0 0 16 16">
<path d="M7.5 1.906v.938h1v-.938zm0 1.875v.938h1V3.78h-1zm0 1.875v.938h1v-.938zM1.906 8.5h.938v-1h-.938zm1.875 0h.938v-1H3.78v1zm1.875 0h.938v-1h-.938zm2.813 0v-.031H8.5V7.53h-.031V7.5H7.53v.031H7.5v.938h.031V8.5zm.937 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zM7.5 9.406v.938h1v-.938zm0 1.875v.938h1v-.938zm0 1.875v.938h1v-.938z" />
<path d="M0 0v16h16V0zm1 1h14v14H1z" />
</svg><span class="mx-2 mt-0">Crochet</span>
</NavLink>
</li>
<li> <li>
<NavLink class="nav-link" href="pokemonsleep"> <NavLink class="nav-link" href="pokemonsleep">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-p-circle-fill" viewBox="0 0 16 16">

View File

@ -1,16 +0,0 @@
@page "/temperature-blanket"
@attribute [StreamRendering]
@rendermode InteractiveServer
<PageTitle>Crochet Tools</PageTitle>
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-cosmo.css" /> <!-- app.css -->
</head>
<h3 class="text-xl font-bold mb-4">Crochet</h3>
<div class="">
<TemperatureBlanketVisualizer TemperatureDays="temperatureDays" />
</div>

View File

@ -1,69 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.TemperatureDay;
using Portfolio.Domain.Features.TemperatureRange;
using Portfolio.WebUI.Server.Components.Component.Crochet_Components;
using static Portfolio.WebUI.Server.Components.Component.Crochet_Components.TemperatureRangeEditor;
namespace Portfolio.WebUI.Server.Components.Pages.Crochet_Pages
{
public partial class CrochetHome
{
public List<TemperatureDay> temperatureDays { get; set; }
public int YEAR = 2025;
protected override async Task OnInitializedAsync()
{
// Placeholder for loading temperature data
// Replace with actual API call
//temperatureDays = Enumerable.Range(0, 365).Select(i => new TemperatureDay
//{
// Date = new DateTime(DateTime.Now.Year - 1, 1, 1).AddDays(i),
// AvgTemp = Random.Shared.Next(10, 95)
//}).ToList();
temperatureDays = GenerateRealisticTemperatureDays(YEAR);
}
public static List<TemperatureDay> GenerateRealisticTemperatureDays(int year)
{
var temperatureDays = new List<TemperatureDay>();
var startDate = new DateTime(year, 1, 1);
int daysInYear = DateTime.IsLeapYear(year) ? 366 : 365;
// Adjusted parameters for desired range
double minAvgTemp = 20.0;
double maxAvgTemp = 84.0;
double amplitude = (maxAvgTemp - minAvgTemp) / 2.0; // 32.5
double avgAnnualTemp = (maxAvgTemp + minAvgTemp) / 2.0; // 52.5
double noiseMax = 3.0; // Small daily variation
for (int i = 0; i < daysInYear; i++)
{
var date = startDate.AddDays(i);
double dayOfYearRatio = (2 * Math.PI * i) / daysInYear;
// Peak is mid-summer, trough is mid-winter
double seasonalTemp = avgAnnualTemp + amplitude * Math.Sin(dayOfYearRatio - Math.PI / 2);
// Add gentle noise
double dailyNoise = Random.Shared.NextDouble() * noiseMax * 2 - noiseMax;
// Final temperature, clamped to min/max
double finalTemp = Math.Round(seasonalTemp + dailyNoise, 1);
finalTemp = Math.Clamp(finalTemp, minAvgTemp, maxAvgTemp);
temperatureDays.Add(new TemperatureDay
{
Date = date,
AvgTemp = finalTemp
});
}
return temperatureDays;
}
}
}

View File

@ -1,24 +0,0 @@
@* @page "/import-temperature-data"
@inject NWSWeatherService WeatherService
@inject IWebHostEnvironment Env
<h3>Import Temperature Data</h3>
@if (IsImporting)
{
<p>Importing temperatures... Please wait...</p>
}
else
{
<button class="btn btn-primary" @onclick="ImportAndSaveYearAsync">Import 2024 Data</button>
}
@if (!string.IsNullOrEmpty(Message))
{
<p>@Message</p>
}
*@

View File

@ -1,69 +0,0 @@
using Portfolio.Application.Services.NWSWeatherService;
using Portfolio.Domain.Features.TemperatureDay;
using System.Text.Json;
namespace Portfolio.WebUI.Server.Components.Pages.Crochet_Pages
{
public partial class TemperatureDataImporter
{
private readonly NWSWeatherService _weatherService;
private readonly string _storagePath = "Data/temperature_data_2024.json"; // changeable if needed
public bool IsImporting = true;
public TemperatureDataImporter(NWSWeatherService weatherService)
{
_weatherService = weatherService;
}
public async Task<List<TemperatureDay>> ImportAndSaveYearAsync(int year, double latitude, double longitude)
{
var days = new List<TemperatureDay>();
var stationId = await _weatherService.GetNearestStationAsync(latitude, longitude);
if (stationId == null)
{
throw new Exception("Failed to find nearest station.");
}
var startDate = new DateTime(year, 1, 1);
var endDate = new DateTime(year, 12, 31);
for (var date = startDate; date <= endDate; date = date.AddDays(1))
{
var avgTemp = await _weatherService.GetDailyAverageTempAsync(stationId, date);
if (avgTemp.HasValue)
{
days.Add(new TemperatureDay { Date = date, AvgTemp = avgTemp.Value });
}
await Task.Delay(600); // Respectful API use
}
await SaveToFileAsync(days);
return days;
}
private async Task SaveToFileAsync(List<TemperatureDay> days)
{
Directory.CreateDirectory(Path.GetDirectoryName(_storagePath)!);
var json = JsonSerializer.Serialize(days, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(_storagePath, json);
Console.WriteLine($"✅ Saved {days.Count} days to {_storagePath}");
}
public async Task<List<TemperatureDay>> LoadSavedDataAsync()
{
if (!File.Exists(_storagePath))
throw new FileNotFoundException($"No saved temperature data found at {_storagePath}");
var json = await File.ReadAllTextAsync(_storagePath);
var days = JsonSerializer.Deserialize<List<TemperatureDay>>(json);
return days ?? new List<TemperatureDay>();
}
}
}

View File

@ -7,8 +7,3 @@
<p>Ensuring that git is connected properly.</p> <p>Ensuring that git is connected properly.</p>
Welcome to your new app. Welcome to your new app.
<div class="w-75 h-100 bg-white">
</div>

View File

@ -17,7 +17,7 @@
} }
else else
{ {
<div class="w-50 mt-5 m-auto create-container bg-info"> <div class="w-50 mt-5 m-auto create-container">
<div class="card-header bg-secondary bg-gradient ml-0 py-3"> <div class="card-header bg-secondary bg-gradient ml-0 py-3">
<div class="row"> <div class="row">
@ -86,7 +86,6 @@ else
<option value="Berries">Berries</option> <option value="Berries">Berries</option>
<option value="Ingredients">Ingredients</option> <option value="Ingredients">Ingredients</option>
<option value="Skills">Skills</option> <option value="Skills">Skills</option>
<option value="All">All</option>
</InputSelect> </InputSelect>
</div> </div>
</div> </div>
@ -112,18 +111,11 @@ else
<label for="ImageUrl" class="form-label">Base Image URL</label> <label for="ImageUrl" class="form-label">Base Image URL</label>
<InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonImageUrl" class="form-control" /> <InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonImageUrl" class="form-control" />
</div> </div>
<!-- Shiny Image URL Input -->
<div class="row mb-3 m-auto"> <div class="row mb-3 m-auto">
<label for="ImageUrl" class="form-label">Shiny Image URL</label> <label for="ImageUrl" class="form-label">Shiny Image URL</label>
<InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonShinyImageUrl" class="form-control" /> <InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonShinyImageUrl" class="form-control" />
</div> </div>
<!-- Flavor Text Input -->
<div class="row mb-3 m-auto">
<label for="FlavorText" class="form-label">Flavor Text</label>
<InputText id="FlavorText" @bind-Value="NewPokemon.FlavorText" class="form-control" />
</div>
<!-- Form Buttons --> <!-- Form Buttons -->
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<button type="button" class="btn btn-secondary mb-3" @onclick="Cancel">Cancel</button> <button type="button" class="btn btn-secondary mb-3" @onclick="Cancel">Cancel</button>

View File

@ -32,13 +32,13 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
isSubmitting = true; isSubmitting = true;
await PokemonService.AddPokemonAsync(NewPokemon); await PokemonService.AddPokemonAsync(NewPokemon);
isSubmitting = false; isSubmitting = false;
Navigation.NavigateTo("/pokemon"); Navigation.NavigateTo("/pokemonsleep");
} }
protected void Cancel(MouseEventArgs e) protected void Cancel(MouseEventArgs e)
{ {
Console.WriteLine("Testing in Cancel"); Console.WriteLine("Testing in Cancel");
Navigation.NavigateTo("/pokemon"); Navigation.NavigateTo("/pokemonsleep");
} }
} }

View File

@ -8,9 +8,6 @@
<PageTitle>Edit Pokémon</PageTitle> <PageTitle>Edit Pokémon</PageTitle>
<PokemonHeader /> <PokemonHeader />
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-lumen.css" /> <!-- app.css -->
</head>
@if (pokemon == null) @if (pokemon == null)
{ {

View File

@ -1,66 +1,185 @@
@page "/rate-pokemon" @page "/pokemonsleep/rate-pokemon"
@inject IPokemonService PokemonService @inject IPokemonService PokemonService
@inject IPokemonNatureService PokemonNatureService @inject IPokemonNatureService PokemonNatureService
@inject IPokemonSubskillService PokemonSubskillService @inject IPokemonSubskillService PokemonSubskillService
@inject NavigationManager Navigation
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-lumen.css" /> <!-- app.css -->
</head>
<PageTitle>Rate Pokémon</PageTitle> <PageTitle>Rate Pokémon</PageTitle>
<PokemonHeader /> <PokemonHeader />
<div class="mt-4">
<div class="row">
@if (PokemonList == null || NatureList == null || SubskillList == null) @if (PokemonList == null || NatureList == null || SubskillList == null)
{ {
<div class="d-flex justify-content-center align-items-center" style="height: 60vh;"> <p>Loading...</p>
<Loading />
</div>
} }
else else
{ {
<!-- Left Panel: Selector --> <!-- Total Component -->
<div class="col-4"> <div class="w-75 mt-3 m-auto rate-container bg-info ">
<PokemonSelector
PokemonList="PokemonList" <!-- Header -->
SelectedPokemon="SelectedPokemon" <div class="card-header bg-secondary ml-0 py-3 w-100 ">
OnPokemonSelected="SelectPokemon" /> <div class="row">
<div class=" text-center">
<h2 class="text-info">Pokémon Rater</h2>
</div>
</div>
</div> </div>
<!-- Center Panel: Pokemon View --> <!-- Body -->
<div class="col-4"> <div class="p-3 w-100 flex-column ">
<div class="d-flex justify-content-center align-items-center h-100"> <!-- Section 1: Top - Pokemon Selection -->
<div class="row flex-row justify-content-end">
<div class="pokemon-search col">
<div class="position-relative pb-3" >
<!-- Pokemon Selection -->
<input type="text"
class="form-control form-control"
@bind="PokemonSearchTerm"
placeholder="Search Pokémon..."
@oninput="OnSearchTextChanged"
/>
@if (FilteredPokemonList.Any() && !string.IsNullOrWhiteSpace(PokemonSearchTerm))
{
<ul class="list-group position-absolute w-100" style="z-index: 1000; max-height: 200px; overflow-y: auto;">
@foreach (var pokemon in FilteredPokemonList)
{
<li class="list-group-item list-group-item-action" @onclick="() => SelectPokemon(pokemon)">
@if (pokemon.IsVariation)
{
@($"{pokemon.PokemonId} {pokemon.VariationName} {pokemon.PokemonName}")
}
else
{
@($"{pokemon.PokemonId} {pokemon.PokemonName}")
}
</li>
}
</ul>
}
</div>
</div>
<div class="col-2">
<button class="btn btn-danger">Clear</button>
</div>
</div>
<!-- Section 2: Bottom - Pokemon -->
@if (SelectedPokemon != null) @if (SelectedPokemon != null)
{ {
<div class="row w-100">
<!-- Section 2A: Left Side - Pokemon Card View -->
<div class="col">
<div class="position-relative d-flex justify-content-center">
<PokemonCard Pokemon="SelectedPokemon" /> <PokemonCard Pokemon="SelectedPokemon" />
} </div>
else </div>
<!-- Section 2B: Right Side - Stat Selection + Form Submission -->
<div class="col">
<h4 class="mb-3">Select Nature & Subskills</h4>
<!-- Nature -->
<div class="">
<div class="">
<label>Select Nature</label>
<select class="form-control form-control-sm mb-2" @bind="SelectedNatureId">
<option value="" disabled>Choose Nature...</option>
@foreach (var nature in NatureList)
{ {
<p class="text-muted">Please select a Pokémon to rate.</p> <option value="@nature.Id">@nature.Nature</option>
}
</select>
</div>
</div>
<!-- Subskill 1 -->
<div class="">
<div class="">
<label for="subskillSelect1">Select Level 10 Subskill</label>
<select id="subskillSelect1" class="form-control form-control-sm mb-2" @bind="subskillSelect1">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
<!-- Subskill 2 -->
<div class="">
<div class="">
<label for="subskillSelect2">Select Level 25 Subskill</label>
<select id="subskillSelect2" class="form-control form-control-sm mb-2" @bind="subskillSelect2">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
<!-- Subskill 3 -->
<div class="">
<div class="">
<label for="subskillSelect3">Select Level 50 Subskill</label>
<select id="subskillSelect3" class="form-control form-control-sm mb-2" @bind="subskillSelect3">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
<!-- Subskill 4 Disabled -->
<div class="">
<div class="">
<label for="subskillSelect4">Select Level 75 Subskill</label>
<select id="subskillSelect4" disabled class="form-control form-control-sm mb-2" @bind="subskillSelect4">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
<!-- Subskill 5 Disabled -->
<div class="">
<div class="">
<label for="subskillSelect5">Select Level 100 Subskill</label>
<select id="subskillSelect5" disabled class="form-control form-control-sm mb-2" @bind="subskillSelect5">
<option value="" disabled selected>Choose Subskill...</option>
@foreach (var subskill in SubskillList)
{
<option value="@subskill.Id">@subskill.SubSkill</option>
}
</select>
</div>
</div>
<!-- Calculate Score -->
<div class="">
<div class="d-flex justify-content-between align-items-center mt-3">
<button class="btn btn-primary" @onclick="CalculateScore">Calculate Final Score</button>
<h4 class="bg-white border border-1 rounded p-2 m-2">
<span class="finalScore rounded" style="background-color: @ScoreBackgroundColor">@FinalScore</span>
</h4>
</div>
</div>
</div>
</div>
} }
</div> </div>
</div> </div>
<!-- Right Panel: Rating View -->
<div class="col-4">
<PokemonRatingPanel
PokemonToRate="SelectedPokemon"
NatureList="NatureList"
SubskillList="SubskillList"
/>
</div>
} }
</div>
<hr class="mt-5"/>
</div>

View File

@ -58,8 +58,7 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{ {
SelectedPokemon = pokemon; SelectedPokemon = pokemon;
PokemonSearchTerm = string.Empty; // Reset search term PokemonSearchTerm = string.Empty; // Reset search term
StateHasChanged(); FilteredPokemonList.Clear(); // Clear the filtered list to hide dropdown
//FilteredPokemonList.Clear(); // Clear the filtered list to hide dropdown
} }
private async void OnPokemonSelected() private async void OnPokemonSelected()

View File

@ -1 +1,92 @@
 
.rate-container {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2),
0 6px 20px 0 rgba(255,255, 255, 0.19);
border-radius: 15px;
}
.pokemon-search {
width: 95%;
}
.flip-container {
perspective: 1000px;
display: inline-block;
width: 250px;
height: 250px;
cursor: pointer;
}
.flipper {
transition: transform 0.6s;
transform-style: preserve-3d;
width: 100%;
height: 100%;
position: relative;
}
.flipped {
transform: rotateY(180deg);
}
.front, .back {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
}
.back {
transform: rotateY(180deg);
}
.badge {
width: 90px;
height: 30px;
color: white;
padding: 4px 8px;
border-radius: 30px;
}
.statText {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 13px;
}
.dozing {
background-color: #fcdc5e;
}
.snoozing {
background-color: #4ce8ed;
}
.slumbering {
background-color: #4588fb;
}
.berries {
background-color: #24d86b;
}
.ingredients {
background-color: #fdbe4d;
}
.skills {
background-color: #47a0fc;
}
.finalScore {
color: white;
padding: 4px 8px;
text-align: center;
vertical-align: middle;
border-radius: 3px;
}

View File

@ -9,10 +9,6 @@
<PageTitle>Pokémon Sleep</PageTitle> <PageTitle>Pokémon Sleep</PageTitle>
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-lumen.css" /> <!-- app.css -->
</head>
<div class="w-100"> <div class="w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> --> <!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
@ -20,7 +16,4 @@
<PokemonTable AllPokemon="pokemons"/> <PokemonTable AllPokemon="pokemons"/>
<hr class="mt-5" />
</div> </div>

View File

@ -6,28 +6,14 @@
<PageTitle>Pokémon Sleep</PageTitle> <PageTitle>Pokémon Sleep</PageTitle>
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-lumen.css" /> <!-- app.css -->
</head>
<div class=""> <div class="w-100">
<div class="row w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> --> <!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<div class="row"><PokemonHeader /></div> <PokemonHeader />
<div class="card shadow border-0 p-3 mt-4 m-auto w-75">
<!-- Card --> <div class="d-flex flex-row justify-content-around">
<div class="row card shadow-sm border-0 p-3 pb-4 mt-4 m-auto w-75 mb-5 bg-white"> <div class="card border-0 shadow-sm"><img class="card-img shadow-sm w-auto" style="width: 540px; height: 540px;" src="images/Pokemon_Sleep_ID.jpg" /></div>
<!-- Top Row--> <div class="border border-warning w-50 p-3">
<div class="row d-flex flex-row">
<!-- Image side -->
<div class="col w-50 border-0 ">
<div>
</div>
<img class="shadow-sm w-100 m-auto img-fluid" src="images/Pokemon_Sleep_ID.jpg" />
</div>
<!-- Text side -->
<div class="col w-50 p-3">
<p class="fw-bold fst-italic fs-3">Pokémon Sleep? Really?</p> <p class="fw-bold fst-italic fs-3">Pokémon Sleep? Really?</p>
<p class="fw-normal fs-6 text-start"> <p class="fw-normal fs-6 text-start">
Yes, really! Pokémon Sleep has become a fun addition to my day since it's release. Yes, really! Pokémon Sleep has become a fun addition to my day since it's release.
@ -36,41 +22,17 @@
<p class="fw-normal fs-6 text-start"> <p class="fw-normal fs-6 text-start">
That's harder to explain. See, it isn't as much a game, as it is a gamified sleep tracker. But it's fun to collect the Pokémon and gather their berries and ingredients and create silly little Pokémon-themed foods. Plus, it encourages me to try to get to bed in a timely manner; though, if I'm honest, I definitely put my Pokémon to bed ahead of when I do. That's harder to explain. See, it isn't as much a game, as it is a gamified sleep tracker. But it's fun to collect the Pokémon and gather their berries and ingredients and create silly little Pokémon-themed foods. Plus, it encourages me to try to get to bed in a timely manner; though, if I'm honest, I definitely put my Pokémon to bed ahead of when I do.
</p> </p>
</div>
</div>
<!-- Second Row -->
<div class="row mt-3">
<p class="fw-bold fst-italic fs-3">Okay, but why a whole section dedicated to Pokémon Sleep?</p> <p class="fw-bold fst-italic fs-3">Okay, but why a whole section dedicated to Pokémon Sleep?</p>
<p class="fw-normal fs-6 text-start"> <p class="fw-normal fs-6 text-start">
Well, as it is in any Pokémon game, Natures (and in this case Subskills) matter, amongst other things. This was designed as a helpful tool in assessing new Pokémon acquired from Sleep Research. Well, as it is in any Pokémon game, Natures (and in this case Subskills) matter, amongst other things. This was designed as a helpful tool in assessing new Pokémon acquired from Sleep Research.
</p> </p>
</div> </div>
<!-- Button Row-->
<div class="row btn-group d-flex flex-row justify-content-around mt-4">
<div class="w-auto">
<button class="btn btn-info">
<NavLink href="/pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-table mb-1" viewBox="0 0 16 16">
<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm15 2h-4v3h4zm0 4h-4v3h4zm0 4h-4v3h3a1 1 0 0 0 1-1zm-5 3v-3H6v3zm-5 0v-3H1v2a1 1 0 0 0 1 1zm-4-4h4V8H1zm0-4h4V4H1zm5-3v3h4V4zm4 4H6v3h4z" />
</svg>
<span class="ps-1">Available Pokémon</span>
</NavLink>
</button>
</div> </div>
<div class="w-auto"> <div class="btn-group d-flex flex-row justify-content-around mt-4">
<button class="btn btn-success link"> <button class="btn btn-info">Available Pokémon</button>
<NavLink href="/rate-pokemon"> <button class="btn btn-success">Rate Pokémon</button>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-award-fill mb-1" viewBox="0 0 16 16"> </div>
<path d="m8 0 1.669.864 1.858.282.842 1.68 1.337 1.32L13.4 6l.306 1.854-1.337 1.32-.842 1.68-1.858.282L8 12l-1.669-.864-1.858-.282-.842-1.68-1.337-1.32L2.6 6l-.306-1.854 1.337-1.32.842-1.68L6.331.864z" />
<path d="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" />
</svg>
<span class="ps-1">Rate Pokémon</span>
</NavLink>
</button>
</div> </div>
</div>
</div>
</div>
</div> </div>

View File

@ -8,10 +8,6 @@
<PokemonHeader /> <PokemonHeader />
<head>
<link rel="stylesheet" href="bootstrap/bootstrap-lumen.css" /> <!-- app.css -->
</head>
@if (_pokemon == null) @if (_pokemon == null)
{ {
<Loading /> <Loading />
@ -21,20 +17,14 @@ else
<PageTitle>@_pokemon.PokemonName</PageTitle> <PageTitle>@_pokemon.PokemonName</PageTitle>
<!-- Total Componenet--> <!-- Total Componenet-->
<div class="container"> <div class="w-100">
<div class="w-75 row mt-4 m-auto"> <div class="d-flex justify-content-center mt-4">
<!-- Previous Pokemon Button -->
<div class="col-auto">
<button class="mt-1 p-2 btn btn-danger rounded-5 align-self-start text-white" disabled="@(!_previousPokemonId.HasValue)" @onclick="NavigateToPrevious"> <button class="mt-1 p-2 btn btn-danger rounded-5 align-self-start text-white" disabled="@(!_previousPokemonId.HasValue)" @onclick="NavigateToPrevious">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-arrow-left-circle-fill" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-arrow-left-circle-fill" viewBox="0 0 16 16">
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0m3.5 7.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5z" /> <path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0m3.5 7.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5z" />
</svg> </svg>
</button> </button>
</div> <div class="mt-5 mx-5 d-flex justify-content-center">
<!-- Pokemon Presentation -->
<div class="mt-5 mx-5 col justify-content-center">
@if (_variationPokemonId != null) @if (_variationPokemonId != null)
{ {
@if (_variationPokemonId != null && _pokemonVariant == null){ @if (_variationPokemonId != null && _pokemonVariant == null){
@ -42,47 +32,45 @@ else
} }
else else
{ {
<!-- If Variation Pokemon have same PokemonId -->
@if(_pokemon.Id != _pokemonVariant.Id) @if(_pokemon.Id != _pokemonVariant.Id)
{ {
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div class="pokemoncard m-1"> <div class="position-relative">
<PokemonCard Pokemon="_pokemon" /> <PokemonCard Pokemon="_pokemon" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemon.Id" />
</div> </div>
</div>
<div class="pokemoncard m-1"> <div class="position-relative">
<PokemonCard Pokemon="_pokemonVariant" /> <PokemonCard Pokemon="_pokemonVariant" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemonVariant.Id" />
</div>
</div> </div>
</div> </div>
} }
<!-- If Variation Pokemon has diff PokemonId -->
else else
{ {
<div class="d-flex justify-content-center align-items-center h-100"> <div class="position-relative">
<div class="pokemoncard">
<PokemonCard Pokemon="_pokemonVariant" /> <PokemonCard Pokemon="_pokemonVariant" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemonVariant.Id" />
</div> </div>
</div> </div>
} }
} }
} }
else{ else{
<!-- Standard Pokemon Display --> <div class="position-relative">
<div class="d-flex justify-content-center align-items-center h-100">
<div class="pokemoncard m-1">
<PokemonCard Pokemon="_pokemon" /> <PokemonCard Pokemon="_pokemon" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemon.Id" />
</div> </div>
</div> </div>
} }
</div> </div>
<!-- Next Pokemon Button -->
<div class="col-auto">
<button class="mt-1 p-2 btn btn-danger rounded rounded-5 align-self-start text-white" disabled="@(!_nextPokemonId.HasValue)" @onclick="NavigateToNext"> <button class="mt-1 p-2 btn btn-danger rounded rounded-5 align-self-start text-white" disabled="@(!_nextPokemonId.HasValue)" @onclick="NavigateToNext">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-arrow-right-circle-fill" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-arrow-right-circle-fill" viewBox="0 0 16 16">
<path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0M4.5 7.5a.5.5 0 0 0 0 1h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5z" /> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0M4.5 7.5a.5.5 0 0 0 0 1h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5z" />
@ -90,6 +78,4 @@ else
</button> </button>
</div> </div>
</div> </div>
</div>
} }

View File

@ -1,9 +1,2 @@
.pokemoncard { body {
width: 100%;
max-width: 350px;
flex: 0 0 auto; /* prevent flex shrink/grow */
display: flex;
justify-content: center;
align-items: center;
padding: 0.5rem;
} }

View File

@ -10,14 +10,11 @@
@using Portfolio.WebUI.Server.Components @using Portfolio.WebUI.Server.Components
@using Portfolio.WebUI.Server.Components.Component @using Portfolio.WebUI.Server.Components.Component
@using Portfolio.WebUI.Server.Components.Component.Pokemon_Components @using Portfolio.WebUI.Server.Components.Component.Pokemon_Components
@using Portfolio.WebUI.Server.Components.Component.Crochet_Components
@using Portfolio.Domain.Features.Articles @using Portfolio.Domain.Features.Articles
@using Portfolio.Domain.Features.Pokemon @using Portfolio.Domain.Features.Pokemon
@using Portfolio.Domain.Features.Pokemon_Natures @using Portfolio.Domain.Features.Pokemon_Natures
@using Portfolio.Domain.Features.Pokemon_Subskills @using Portfolio.Domain.Features.Pokemon_Subskills
@using Portfolio.Domain.Features.TemperatureDay
@using Portfolio.Application.Services.Articles @using Portfolio.Application.Services.Articles
@using Portfolio.Application.Services.PokemonService @using Portfolio.Application.Services.PokemonService
@using Portfolio.Application.Services.PokemonNatureService @using Portfolio.Application.Services.PokemonNatureService
@using Portfolio.Application.Services.PokemonSubskillService @using Portfolio.Application.Services.PokemonSubskillService
@using Portfolio.Application.Services.NWSWeatherService

View File

@ -1,9 +0,0 @@
window.getScreenWidth = () => {
return window.innerWidth;
};
window.registerResizeCallback = (dotNetHelper) => {
window.onresize = () => {
dotNetHelper.invokeMethodAsync('UpdateScreenWidth', window.innerWidth);
};
};