Compare commits

..

No commits in common. "master" and "feature/temperature-blanket" have entirely different histories.

100 changed files with 1453 additions and 18532 deletions

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,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Domain.Features.Pokemon
{
public class Ingredient
{
public string Name { get; set; }
public string Description { get; set; }
public string ImageURL { get; set; }
}
}

View File

@ -13,18 +13,12 @@ namespace Portfolio.Domain.Features.Pokemon
public required string PokemonName { get; set; } public required string PokemonName { get; set; }
public bool IsVariation { get; set; } = false; public bool IsVariation { get; set; } = false;
public string? VariationName { get; set; } public string? VariationName { get; set; }
public required string PokemonType { get; set; } public string? PokemonType { get; set; }
public required string SleepType { get; set; } public required string SleepType { get; set; }
public required string Speciality { get; set; } public required string Speciality { get; set; }
public string? Skill { get; set; }
public string? SkillDescription { get; set; }
public string? PokemonImageUrl { get; set; } public string? PokemonImageUrl { get; set; }
public string? PokemonShinyImageUrl { get; set; } public string? PokemonShinyImageUrl { get; set; }
public string[]? PokemonSleepStyleImageUrls { get; set; }
public string? FlavorText { get; set; } public string? FlavorText { get; set; }
public string? Ingredient1 { get; set; }
public string? Ingredient2 { get; set; }
public string? Ingredient3 { get; set; }
} }

View File

@ -1,18 +0,0 @@
using Portfolio.Domain.Features.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Domain.Features.Pokemon
{
public class PokemonType : Entity
{
public string Type { get; set; }
public string TypeImageUrl { get; set; }
public string Berry { get; set; }
public string BerryDescription { get; set; }
public string BerryImageUrl { 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.Portfolio
{
public class ProjectEntry
{
public string Title { get; set; }
public List<string> Descriptions { get; set; }
public List<ProjectLink> Links { 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.Portfolio
{
public class ProjectLink
{
public string Type { get; set; }
public string Url { get; set; }
public string Label { get; set; }
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Portfolio.Domain.Features.Portfolio
{
public class WorkExperience
{
public string Title { get; set; }
public string Company { get; set; }
public int StartYear { get; set; }
public int EndYear { get; set; }
public string Details { get; set; }
}
}

View File

@ -1,7 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using Portfolio.Application.Services.Articles; using Portfolio.Application.Services.Articles;
using Portfolio.Application.Services.NWSWeatherService; using Portfolio.Application.Services.NWSWeatherService;
using Portfolio.Application.Services.PokemonService; using Portfolio.Application.Services.PokemonService;

View File

@ -1,130 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Portfolio.Infrastructure;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20251117160500_updatePokemonAddIngredients")]
partial class updatePokemonAddIngredients
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FlavorText")
.HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("Ingredients")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsVariation")
.HasColumnType("bit");
b.Property<int>("PokemonId")
.HasColumnType("int");
b.Property<string>("PokemonImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonShinyImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonType")
.HasColumnType("nvarchar(max)");
b.Property<string>("SleepType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Speciality")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("VariationName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Pokemons");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRating")
.HasColumnType("int");
b.Property<int>("IngredientRating")
.HasColumnType("int");
b.Property<string>("Nature")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SkillRating")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("PokemonNatures");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRank")
.HasColumnType("int");
b.Property<int>("IngredientRank")
.HasColumnType("int");
b.Property<int>("SkillRank")
.HasColumnType("int");
b.Property<string>("SubSkill")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("PokemonSubskills");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class updatePokemonAddIngredients : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Ingredients",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Ingredients",
table: "Pokemons");
}
}
}

View File

@ -1,136 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Portfolio.Infrastructure;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20251117171147_updatePokemonChangeIngredient")]
partial class updatePokemonChangeIngredient
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FlavorText")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient1")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient2")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient3")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsVariation")
.HasColumnType("bit");
b.Property<int>("PokemonId")
.HasColumnType("int");
b.Property<string>("PokemonImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonShinyImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonType")
.HasColumnType("nvarchar(max)");
b.Property<string>("SleepType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Speciality")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("VariationName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Pokemons");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRating")
.HasColumnType("int");
b.Property<int>("IngredientRating")
.HasColumnType("int");
b.Property<string>("Nature")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SkillRating")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("PokemonNatures");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRank")
.HasColumnType("int");
b.Property<int>("IngredientRank")
.HasColumnType("int");
b.Property<int>("SkillRank")
.HasColumnType("int");
b.Property<string>("SubSkill")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("PokemonSubskills");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,48 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class updatePokemonChangeIngredient : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Ingredients",
table: "Pokemons",
newName: "Ingredient3");
migrationBuilder.AddColumn<string>(
name: "Ingredient1",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Ingredient2",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Ingredient1",
table: "Pokemons");
migrationBuilder.DropColumn(
name: "Ingredient2",
table: "Pokemons");
migrationBuilder.RenameColumn(
name: "Ingredient3",
table: "Pokemons",
newName: "Ingredients");
}
}
}

View File

@ -1,149 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Portfolio.Infrastructure;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20251205171834_updatePokemonAddBerry+Skill+SleepStyles")]
partial class updatePokemonAddBerrySkillSleepStyles
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FlavorText")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient1")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient2")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient3")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsVariation")
.HasColumnType("bit");
b.Property<string>("PokemonBerry")
.HasColumnType("nvarchar(max)");
b.Property<int>("PokemonId")
.HasColumnType("int");
b.Property<string>("PokemonImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonShinyImageUrl")
.HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("PokemonSleepStyleImageUrls")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Skill")
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillDescription")
.HasColumnType("nvarchar(max)");
b.Property<string>("SleepType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Speciality")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("VariationName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Pokemons");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRating")
.HasColumnType("int");
b.Property<int>("IngredientRating")
.HasColumnType("int");
b.Property<string>("Nature")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SkillRating")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("PokemonNatures");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRank")
.HasColumnType("int");
b.Property<int>("IngredientRank")
.HasColumnType("int");
b.Property<int>("SkillRank")
.HasColumnType("int");
b.Property<string>("SubSkill")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("PokemonSubskills");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,76 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class updatePokemonAddBerrySkillSleepStyles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "PokemonType",
table: "Pokemons",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AddColumn<string>(
name: "PokemonBerry",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "PokemonSleepStyleImageUrls",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Skill",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "SkillDescription",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PokemonBerry",
table: "Pokemons");
migrationBuilder.DropColumn(
name: "PokemonSleepStyleImageUrls",
table: "Pokemons");
migrationBuilder.DropColumn(
name: "Skill",
table: "Pokemons");
migrationBuilder.DropColumn(
name: "SkillDescription",
table: "Pokemons");
migrationBuilder.AlterColumn<string>(
name: "PokemonType",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
}
}
}

View File

@ -1,146 +0,0 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Portfolio.Infrastructure;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20251205172848_updatePokemonRemovedBerry")]
partial class updatePokemonRemovedBerry
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon.Pokemon", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FlavorText")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient1")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient2")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient3")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsVariation")
.HasColumnType("bit");
b.Property<int>("PokemonId")
.HasColumnType("int");
b.Property<string>("PokemonImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonShinyImageUrl")
.HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("PokemonSleepStyleImageUrls")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Skill")
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillDescription")
.HasColumnType("nvarchar(max)");
b.Property<string>("SleepType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Speciality")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("VariationName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Pokemons");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Natures.PokemonNature", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRating")
.HasColumnType("int");
b.Property<int>("IngredientRating")
.HasColumnType("int");
b.Property<string>("Nature")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("SkillRating")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("PokemonNatures");
});
modelBuilder.Entity("Portfolio.Domain.Features.Pokemon_Subskills.PokemonSubskill", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BerryRank")
.HasColumnType("int");
b.Property<int>("IngredientRank")
.HasColumnType("int");
b.Property<int>("SkillRank")
.HasColumnType("int");
b.Property<string>("SubSkill")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("PokemonSubskills");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Portfolio.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class updatePokemonRemovedBerry : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PokemonBerry",
table: "Pokemons");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PokemonBerry",
table: "Pokemons",
type: "nvarchar(max)",
nullable: true);
}
}
}

View File

@ -32,15 +32,6 @@ namespace Portfolio.Infrastructure.Migrations
b.Property<string>("FlavorText") b.Property<string>("FlavorText")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient1")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient2")
.HasColumnType("nvarchar(max)");
b.Property<string>("Ingredient3")
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsVariation") b.Property<bool>("IsVariation")
.HasColumnType("bit"); .HasColumnType("bit");
@ -57,17 +48,7 @@ namespace Portfolio.Infrastructure.Migrations
b.Property<string>("PokemonShinyImageUrl") b.Property<string>("PokemonShinyImageUrl")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.PrimitiveCollection<string>("PokemonSleepStyleImageUrls")
.HasColumnType("nvarchar(max)");
b.Property<string>("PokemonType") b.Property<string>("PokemonType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Skill")
.HasColumnType("nvarchar(max)");
b.Property<string>("SkillDescription")
.HasColumnType("nvarchar(max)"); .HasColumnType("nvarchar(max)");
b.Property<string>("SleepType") b.Property<string>("SleepType")

View File

@ -1,10 +0,0 @@
To Update Entites in the Database:
1. Make necessary changes to Enttities within .Domain
2. Open NuGet Packet Manager
3. Ensure default project is pointed to .Infrastructure
4. Enter `Add-Migration [Migration Tag Name, ex: updateEntityAddChange]`
5. Enter `Update-Database`
6. Check SSMS to ensure changes.

View File

@ -1,22 +1,21 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" class=""> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" /> <base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap-pulse.css" /> <!-- app.css --> <link rel="stylesheet" href="bootstrap/bootstrap-brite.css" /> <!-- app.css -->
<link rel="stylesheet" href="Portfolio.WebUI.Server.styles.css" /> <link rel="stylesheet" href="Portfolio.WebUI.Server.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<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,19 +1,18 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<div class="pt-4"> <div>
@if (TemperatureDays is null || TemperatureRanges is null) @if (TemperatureDays is null || TemperatureRanges is null)
{ {
<Loading /> <Loading />
} }
else else
{ {
<div class="container">
<h3 class="text-xl font-bold mb-4 mt-4">Temperature Blanket Visualizer</h3> <div>
<div class="row"> <h3 class="text-xl font-bold mb-4">Temperature Blanket Reviewer</h3>
<div class="col-10">
<div class="d-flex"> <div style="display: flex; overflow-x: auto; background-color: black; padding: 10px;">
<div class="temperature-blanket">
@foreach (var day in TemperatureDays) @foreach (var day in TemperatureDays)
{ {
var color = GetColorForTemp(day.AvgTemp); var color = GetColorForTemp(day.AvgTemp);
@ -22,13 +21,9 @@
</div> </div>
} }
</div> </div>
</div>
</div>
<div class="col d-flex align-items-center">
<TemperatureRangeEditor TempRanges="@TemperatureRanges" OnRangesChanged="HandleRangesChanged" /> <TemperatureRangeEditor TempRanges="@TemperatureRanges" OnRangesChanged="HandleRangesChanged" />
</div> </div>
</div>
</div>
} }
</div> </div>

View File

@ -20,7 +20,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Crochet_Components
new() { Min = 35, Max = 42, Color = "#add8e6" }, new() { Min = 35, Max = 42, Color = "#add8e6" },
new() { Min = 42, Max = 49, Color = "#00008b" }, new() { Min = 42, Max = 49, Color = "#00008b" },
new() { Min = 49, Max = 56, Color = "#006400" }, new() { Min = 49, Max = 56, Color = "#006400" },
new() { Min = 56, Max = 63, Color = "#07ed07" }, new() { Min = 56, Max = 63, Color = "#90ee90" },
new() { Min = 63, Max = 70, Color = "#ffff00" }, new() { Min = 63, Max = 70, Color = "#ffff00" },
new() { Min = 70, Max = 77, Color = "#ffa500" }, new() { Min = 70, Max = 77, Color = "#ffa500" },
new() { Min = 77, Max = 84, Color = "#ff0000" }, new() { Min = 77, Max = 84, Color = "#ff0000" },

View File

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

View File

@ -4,11 +4,11 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<div class="container" > @* @onmouseup="OnMouseUp" @onmousemove="OnMouseMove" *@ <div class="relative w-full h-24 px-4" @onmouseup="OnMouseUp" @onmousemove="OnMouseMove">
<!-- Base number line --> <!-- Base number line -->
@* <div class="absolute top-1/2 left-0 right-0 h-1 bg-gray-300 transform -translate-y-1/2"></div> *@ <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 --> <!-- Draggable nodes for adjusting range breakpoints -->
@for (int i = 0; i < TempRanges.Count; i++) @for (int i = 0; i < TempRanges.Count; i++)
{ {
var left = i == 0 ? 0 : TempRanges[i - 1].Max; var left = i == 0 ? 0 : TempRanges[i - 1].Max;
@ -19,75 +19,16 @@
@onmousedown="(e) => OnMouseDown(i, e)" @onmousedown="(e) => OnMouseDown(i, e)"
title="@left°F"> title="@left°F">
</div> </div>
} *@ }
<!-- Color pickers for each range --> <!-- Color pickers for each range -->
<div class="card rounded-3"> <div class="flex gap-2 mt-6">
<div class="card-header mb-3 text-center fw-bold">
Temperature Blanket Colors
</div>
@for (int i = 0; i < TempRanges.Count; i++) @for (int i = 0; i < TempRanges.Count; i++)
{ {
var localIndex = 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" <input type="color"
value="@TempRanges[i].Color" value="@TempRanges[i].Color"
@onchange="e => HandleColorChange(e, localIndex)" /> @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 text-nowrap">
@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>
</div> </div>

View File

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

View File

@ -1,12 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace Portfolio.WebUI.Server.Components.Component
{
public partial class Loading
{
[Parameter]
public string LoadingString { get; set; }
}
}

View File

@ -1,19 +0,0 @@
<div class="add-card card border-2 border-secondary-subtle rounded-4"
role="button"
tabindex="0"
@onclick="HandleClick">
<div class="card-body d-flex align-items-center justify-content-center p-4">
<svg xmlns="http://www.w3.org/2000/svg"
width="@IconSize"
height="@IconSize"
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" />
</svg>
</div>
</div>
@code {
}

View File

@ -1,19 +0,0 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonAddButton
{
[Parameter]
public EventCallback OnAdd { get; set; }
[Parameter]
public int IconSize { get; set; } = 64;
private async Task HandleClick()
{
await OnAdd.InvokeAsync();
}
}
}

View File

@ -1,22 +0,0 @@
.add-card {
min-width: 160px;
min-height: 120px;
max-width: 200px;
cursor: pointer;
background-color: var(--bs-info-subtle);
transition: transform .08s ease, box-shadow .08s ease, background-color .08s ease;
}
.add-card:hover {
background-color: var(--bs-light);
transform: translateY(-1px);
}
.add-card:focus {
outline: none;
box-shadow: 0 0 0 .25rem rgba(13,110,253,.25);
}
.add-card[aria-disabled="true"] {
cursor: not-allowed;
}

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,34 +1,17 @@
$width: 200px; .badge {
$height: 80px;
*, *::before, *::after {
box-sizing: border-box;
}
.badge {
display: flex;
align-items: center;
justify-content: center;
width: 90px; width: 90px;
height: 30px; height: 30px;
padding: 0.25rem;
border-radius: 30px;
color: white; color: white;
font-size: clamp(0.7rem, 1vw, 0.9rem); padding: 4px 8px;
text-align: center; border-radius: 30px;
font-weight: 400;
text-shadow: 0 2px 2px rgba(0,0,0,0.25);
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.35);
transition: all 0.2s ease;
white-space: nowrap;
} }
.statText { .statText {
margin: 0; position: relative;
padding: 0; top: 50%;
width: 100%; left: 50%;
text-align: center; transform: translate(-50%, -50%);
font-size: .8rem;
} }
/* Sleep Type Badge Styling */ /* Sleep Type Badge Styling */

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)
@ -22,15 +21,18 @@
</div> </div>
<!-- Pokemon Image --> <!-- Pokemon Image -->
<div class="card-image-slot z-1"> <div class="flip-container z-1" @onclick="() => ToggleImage()">
<PokemonImage baseUrl="@_pokemon.PokemonImageUrl" shinyUrl="@_pokemon.PokemonShinyImageUrl" /> <div class="flipper @(isShiny ? "flipped" : "")">
<img class="pokemon-image front" src="@_pokemon.PokemonImageUrl" />
<img class="pokemon-image back" src="@_pokemon.PokemonShinyImageUrl" />
</div>
</div> </div>
<!-- Pokemon Flavortext --> <!-- Pokemon Flavortext -->
<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
@ -41,7 +43,7 @@
</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" /> <PokemonBadge BadgeItem="@_pokemon.SleepType" />
<PokemonBadge BadgeItem="@_pokemon.Speciality" /> <PokemonBadge BadgeItem="@_pokemon.Speciality" />
@ -49,8 +51,3 @@
</div> </div>
</div> </div>
<div class="mt-5">
<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,16 +1,9 @@
.card-wrapper { .pokemon-card {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.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;
@ -27,31 +20,44 @@
transform: translateY(-13px); transform: translateY(-13px);
} }
.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;
box-shadow: 0 1px 2px 1px rgba(0,0,0,0.35); margin-top: .5rem !important;
border-radius: 20px; margin-right: .5rem !important;
}
.pokemon-image {
width: 100%; /* Look to flip-container for the width/height of image */
height: 100%;
position: absolute;
top: 0;
left: 0;
} }
.pokemon-flavor-text { .pokemon-flavor-text {
@ -70,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;
@ -81,25 +88,50 @@
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;
hyphens: auto; hyphens: auto;
} }
/* Position the image area within the card */ .flip-container {
.card-image-slot { position: absolute !important;
position: absolute; top: 40% !important;
top: 50%; left: 50% !important;
left: 50%; transform: translate(-50%, -50%) !important;
transform: translate(-50%, -20%); perspective: 1000px;
display: inline-block;
width: 20rem;
height: 20rem;
cursor: pointer;
}
.flipper {
transition: transform 0.6s;
transform-style: preserve-3d;
width: 100%; width: 100%;
aspect-ratio: 1 / 1; height: 100%;
max-width: 300px; 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);
}
/* Type Card Styling */ /* Type Card Styling */
@ -213,10 +245,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

@ -1,9 +0,0 @@
@inject IJSRuntime JS
<div class="">
<button class="btn btn-sm btn-primary p-1 rounded rounded-5 align-self-start text-white " @onclick="DownloadPokemonJson">
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor" class="bi bi-arrow-down-circle" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a7 7 0 1 0 14 0A7 7 0 0 0 1 8m15 0A8 8 0 1 1 0 8a8 8 0 0 1 16 0M8.5 4.5a.5.5 0 0 0-1 0v5.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293z" />
</svg>
</button>
</div>

View File

@ -1,31 +0,0 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using Portfolio.Domain.Features.Pokemon;
using System.Text.Json;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
partial class PokemonDownloadButton
{
[Parameter]
public List<Pokemon> _Pokemon { get; set; }
private List<Pokemon> pokemons = new List<Pokemon>();
protected override void OnParametersSet()
{
if (_Pokemon != null)
{
pokemons = _Pokemon.ToList();
}
}
private async Task DownloadPokemonJson()
{
var json = JsonSerializer.Serialize(pokemons, new JsonSerializerOptions { WriteIndented = true });
await JS.InvokeVoidAsync("downloadFileFromText", "pokemon.json", "application/json", json);
}
}
}

View File

@ -9,7 +9,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
private void EditPokemon(int PokemonId) private void EditPokemon(int PokemonId)
{ {
Navigation.NavigateTo($"/pokemon-sleep/edit-pokemon/{PokemonId}"); Navigation.NavigateTo($"/pokemonsleep/edit/{PokemonId}");
} }
} }
} }

View File

@ -1,425 +0,0 @@
@inject IPokemonService PokemonService
@inject IHttpClientFactory ClientFactory
@if(Ingredients == null)
{
<Loading />
}
else
{
@if(formUse == "ADD")
{
<div class="pokemon-form-container m-auto bg-info border border-5 border-info-subtle rounded-4 p-3">
<EditForm class="col" Model="NewPokemon">
<DataAnnotationsValidator />
<div class="bg-primary-subtle rounded"><p class="fs-3 fw-light text-center card-title">New Pokemon</p></div>
<!-- Pokemon Number and Name -->
<div class="row mt-1">
<div class="col input-group mb-2">
<span class="input-group-text text-sm-center rounded-start">#</span>
<InputNumber min="1"
placeholder="Pokedex #"
id="PokemonId"
@bind-Value="NewPokemon.PokemonId"
@onchange="@SendPokemon"
class="form-control "
type="number" />
<InputText placeholder="Pokemon Name"
id="PokemonName"
@bind-Value="NewPokemon.PokemonName"
@onchange="@SendPokemon"
class="form-control w-50 rounded-end" />
</div>
</div>
<!-- Variation Check -->
<div class="d-flex flex-row justify-content-start input-group ">
<InputCheckbox id="IsVariation"
@bind-Value="NewPokemon.IsVariation"
@onclick="@Toggle"
@onchange="@SendPokemon"
class="form-check-input p-3 rounded" />
<span class="input-group-text ms-1 @GetRoundingClass()">Variation?</span>
<InputText placeholder="How So?"
id="VariationName"
@bind-Value="NewPokemon.VariationName"
@onchange="@SendPokemon"
class="form-control rounded-end"
hidden="@HideLabel" />
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
<!-- Pokemon Type -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="PokemonType" class="input-group-text rounded-start">Pokemon Type</span>
<InputSelect id="PokemonType" @bind-Value="NewPokemon.PokemonType" @onchange="@SendPokemon" class="form-select rounded-end">
<option disabled value="" selected>Select...</option>
@foreach (var pt in PkmnTypes)
{
<option value="@pt.Type">@pt.Type</option>
}
</InputSelect>
</div>
</div>
<!-- Pokemon Sleep Type, Specialty -->
<div class="row mb-3 mx-0">
<!-- Sleep Type -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="SleepType" class="input-group-text rounded-top">Sleep Type</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="SleepType" @bind-Value="NewPokemon.SleepType" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var st in SleepTypes)
{
<option value="@st">@st</option>
}
</InputSelect>
</div>
</div>
<!-- Speciality -->
<div class="col ps-1 pe-0">
<div class="row input-group m-auto">
<span for="Speciality" class="input-group-text rounded-top">Specialty</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Speciality" @bind-Value="NewPokemon.Speciality" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var sp in Specialities)
{
<option value="@sp">@sp</option>
}
</InputSelect>
</div>
</div>
</div>
<!-- Pokemon Ingredients -->
<div class="row mb-3 mx-0">
<!-- Ingredient 1 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient1" class="input-group-text rounded-top">Ingredient 1</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient1" @bind-Value="NewPokemon.Ingredient1" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
<!-- Ingredient 2 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient2" class="input-group-text rounded-top">Ingredient 2</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient2" @bind-Value="NewPokemon.Ingredient2" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
<!-- Ingredient 3 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient3" class="input-group-text rounded-top">Ingredient 3</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient3" @bind-Value="NewPokemon.Ingredient3" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
<!-- Images -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="ImageUrl" class="input-group-text rounded-start">Base Image URL</span>
<InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonImageUrl" @onchange="@SendPokemon" class="form-control rounded-end" />
</div>
</div>
<div class="row mb-2">
<div class="input-group m-auto">
<span for="ShinyImageUrl" class="input-group-text rounded-start">Shiny Image URL</span>
<InputText id="ShinyImageUrl" @bind-Value="NewPokemon.PokemonShinyImageUrl" @onchange="@SendPokemon" class="form-control rounded-end" />
</div>
</div>
<!-- Flavor -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="FlavorText" class="input-group-text rounded-start">Flavor Text</span>
<InputText id="FlavorText" @bind-Value="NewPokemon.FlavorText" @onchange="@SendPokemon" class="form-control rounded-end" />
</div>
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
@if (showErrors && !IsComplete)
{
<div class="alert alert-warning mt-2">
Please complete: @string.Join(", ", MissingFields())
</div>
}
<div class="d-flex mt-3 justify-content-center gap-3">
<button type="button"
class="btn btn-success rounded rounded-5 p-1"
@onclick="@SendPokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-plus-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
</svg>
</button>
@if (mostRecentForm)
{
<button type="button"
class="btn btn-danger rounded rounded-5 p-1"
@onclick="@HandleRemove">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708" />
</svg>
</button>
}
else
{
<button type="button"
class="btn btn-danger rounded rounded-5 p-1"
disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708" />
</svg>
</button>
}
</div>
</EditForm>
</div>
}
else if (formUse == "EDIT")
{
<div class="pokemon-form-container m-auto bg-info border border-5 border-info-subtle rounded-4 p-3">
<EditForm class="col" Model="PokemonToEdit">
<DataAnnotationsValidator />
<div class="bg-primary-subtle rounded"><p class="fs-3 fw-light text-center card-title">Edit Pokemon</p></div>
<!-- Pokemon Number and Name -->
<div class="row mt-1">
<div class="col input-group mb-2">
<span class="input-group-text text-sm-center rounded-start">#</span>
<InputNumber min="1"
placeholder="Pokedex #"
id="PokemonId"
@bind-Value="PokemonToEdit.PokemonId"
@onchange="@SendPokemon"
class="form-control "
type="number" />
<InputText placeholder="Pokemon Name"
id="PokemonName"
@bind-Value="PokemonToEdit.PokemonName"
@onchange="@SendPokemon"
class="form-control w-50 rounded-end" />
</div>
</div>
<!-- Variation Check -->
<div class="d-flex flex-row justify-content-start input-group ">
<InputCheckbox id="IsVariation"
@bind-Value="PokemonToEdit.IsVariation"
@onclick="@Toggle"
@onchange="@SendPokemon"
class="form-check-input p-3 rounded" />
<span class="input-group-text ms-1 @GetRoundingClass()">Variation?</span>
<InputText placeholder="How So?"
id="VariationName"
@bind-Value="PokemonToEdit.VariationName"
@onchange="@SendPokemon"
class="form-control rounded-end"
hidden="@HideLabel" />
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
<!-- Pokemon Type -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="PokemonType" class="input-group-text rounded-start">Pokemon Type</span>
<InputSelect id="PokemonType" @bind-Value="PokemonToEdit.PokemonType" class="form-select rounded-end" @onchange="@SendPokemon">
<option disabled value="" selected>Select...</option>
@foreach (var pt in PokemonTypes)
{
<option value="@pt">@pt</option>
}
</InputSelect>
</div>
</div>
<!-- Pokemon Sleep Type, Specialty -->
<div class="row mb-3 mx-0">
<!-- Sleep Type -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="SleepType" class="input-group-text rounded-top">Sleep Type</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="SleepType" @bind-Value="PokemonToEdit.SleepType" class="form-select rounded-bottom" @onchange="@SendPokemon">
<option disabled value="" selected>Select...</option>
@foreach (var st in SleepTypes)
{
<option value="@st">@st</option>
}
</InputSelect>
</div>
</div>
<!-- Speciality -->
<div class="col ps-1 pe-0">
<div class="row input-group m-auto">
<span for="Speciality" class="input-group-text rounded-top">Specialty</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Speciality" @bind-Value="PokemonToEdit.Speciality" class="form-select rounded-bottom" @onchange="@SendPokemon">
<option disabled value="" selected>Select...</option>
@foreach (var sp in Specialities)
{
<option value="@sp">@sp</option>
}
</InputSelect>
</div>
</div>
</div>
<!-- Pokemon Ingredients -->
<div class="row mb-3 mx-0">
<!-- Ingredient 1 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient1" class="input-group-text rounded-top">Ingredient 1</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient1" @bind-Value="PokemonToEdit.Ingredient1" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
<!-- Ingredient 2 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient2" class="input-group-text rounded-top">Ingredient 2</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient2" @bind-Value="PokemonToEdit.Ingredient2" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
<!-- Ingredient 3 -->
<div class="col ps-0 pe-1">
<div class="row input-group m-auto">
<span for="Ingredient3" class="input-group-text rounded-top">Ingredient 3</span>
</div>
<div class="row input-group m-auto">
<InputSelect id="Ingredient3" @bind-Value="PokemonToEdit.Ingredient3" @onchange="@SendPokemon" class="form-select rounded-bottom">
<option disabled value="" selected>Select...</option>
@foreach (var ingredient in Ingredients)
{
<option value="@ingredient.Name">@ingredient.Name</option>
}
</InputSelect>
</div>
</div>
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
<!-- Images -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="ImageUrl" class="input-group-text rounded-start">Base Image URL</span>
<InputText id="ImageUrl" @bind-Value="PokemonToEdit.PokemonImageUrl" class="form-control rounded-end" @onchange="@SendPokemon" />
</div>
</div>
<div class="row mb-2">
<div class="input-group m-auto">
<span for="ShinyImageUrl" class="input-group-text rounded-start">Shiny Image URL</span>
<InputText id="ShinyImageUrl" @bind-Value="PokemonToEdit.PokemonShinyImageUrl" class="form-control rounded-end" @onchange="@SendPokemon" />
</div>
</div>
<!-- Flavor -->
<div class="row mb-2">
<div class="input-group m-auto">
<span for="FlavorText" class="input-group-text rounded-start">Flavor Text</span>
<InputText id="FlavorText" @bind-Value="PokemonToEdit.FlavorText" class="form-control rounded-end" @onchange="@SendPokemon" />
</div>
</div>
<!-- <br> -->
<div class="border-bottom border-3 border-info-subtle rounded m-1 my-3"></div>
@if (showErrors && !IsComplete)
{
<div class="alert alert-warning mt-2">
Please complete: @string.Join(", ", MissingFields())
</div>
}
<div class="d-flex mt-3 justify-content-center gap-3">
@if (mostRecentForm)
{
<button type="button"
class="btn btn-danger rounded rounded-5 p-1"
@onclick="@HandleRemove">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708" />
</svg>
</button>
}
</div>
</EditForm>
</div>
}
}

View File

@ -1,190 +0,0 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Portfolio.Application.Services.PokemonService;
using Portfolio.Domain.Features.Pokemon;
using Portfolio.Domain.Features.Portfolio;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonForm
{
// To Add or Edit Pokemon
[Parameter]
public string formUse { get; set; }
private bool formChanged { get; set; } = false;
[Parameter]
public EventCallback<Pokemon> OnPokemonReady { get; set; }
[Parameter]
public EventCallback RemoveForm { get; set; }
// When Adding
[Parameter]
public bool mostRecentForm { get; set; }
private Pokemon NewPokemon = new Pokemon
{
PokemonId = 0, // Or any default ID logic
PokemonName = string.Empty, // Required fields cannot be null
PokemonType = string.Empty, // Required fields cannot be null
SleepType = string.Empty,
Speciality = string.Empty,
IsVariation = false
};
// When Editing
[Parameter]
public Pokemon? PokemonToEdit { get; set; }
private int PokemonToEditId { get; set; }
// General Form
protected static readonly string[] PokemonTypes = new[]
{
"Grass","Fire","Water","Normal","Flying","Bug","Poison","Electric","Ground","Rock","Ice",
"Steel","Fighting","Psychic","Dark","Fairy","Ghost","Dragon"
};
protected static readonly string[] SleepTypes = new[] { "Dozing", "Snoozing", "Slumbering" };
protected static readonly string[] Specialities = new[] { "Berries", "Ingredients", "Skills", "All" };
private List<Ingredient>? Ingredients;
private List<PokemonType>? PkmnTypes;
private bool HideLabel { get; set; }
private bool showErrors { get; set; } = false;
protected override async Task OnInitializedAsync()
{
var http = ClientFactory.CreateClient("LocalClient");
Ingredients = await http.GetFromJsonAsync<List<Ingredient>>("data/ingredients.json");
PkmnTypes = await http.GetFromJsonAsync<List<PokemonType>>("data/pkmn_type-and-berries.json");
var count = 0;
foreach (var t in PkmnTypes)
{
count++;
//if (count <= 9) { Console.WriteLine("0"+ count + ": | " + t.Type + "\t| " + t.Berry); }
//else { Console.WriteLine(count + ": | " + t.Type + "\t| " + t.Berry); }
}
if (formUse == "EDIT")
{
if (PokemonToEdit.IsVariation == true)
{
HideLabel = false;
}
PokemonToEditId = PokemonToEdit.Id;
}
else
{
HideLabel = true;
}
}
private void Toggle()
{
HideLabel = !HideLabel;
}
private void ToggleFormChange()
{
formChanged = true;
}
// CSS-function to get proper styling for form elements
private string GetRoundingClass()
{
if (!HideLabel)
{
return "rounded-start";
}
return "rounded-start rounded-end";
}
// Minimal "complete" check (no data annotations needed)
private bool IsComplete =>
NewPokemon.PokemonId > 0 &&
!string.IsNullOrWhiteSpace(NewPokemon.PokemonName) &&
!string.IsNullOrWhiteSpace(NewPokemon.PokemonType) &&
!string.IsNullOrWhiteSpace(NewPokemon.SleepType) &&
!string.IsNullOrWhiteSpace(NewPokemon.Speciality) &&
(!NewPokemon.IsVariation || !string.IsNullOrWhiteSpace(NewPokemon.VariationName));
private IEnumerable<string> MissingFields()
{
if (NewPokemon.PokemonId <= 0) yield return "Pokédex #";
if (string.IsNullOrWhiteSpace(NewPokemon.PokemonName)) yield return "Name";
if (string.IsNullOrWhiteSpace(NewPokemon.PokemonType)) yield return "Type";
if (string.IsNullOrWhiteSpace(NewPokemon.SleepType)) yield return "Sleep Type";
if (string.IsNullOrWhiteSpace(NewPokemon.Speciality)) yield return "Specialty";
if (NewPokemon.IsVariation && string.IsNullOrWhiteSpace(NewPokemon.VariationName)) yield return "Variation Name";
}
private async Task HandleRemove()
{
await RemoveForm.InvokeAsync();
}
private async Task SendPokemon()
{
Console.WriteLine("onchange");
if(formUse == "ADD")
{
if (!IsComplete)
{
showErrors = true;
StateHasChanged();
return;
}
// Optionally send a copy to avoid later mutation by the child
var copy = new Pokemon
{
PokemonId = NewPokemon.PokemonId,
PokemonName = NewPokemon.PokemonName,
PokemonType = NewPokemon.PokemonType,
SleepType = NewPokemon.SleepType,
Speciality = NewPokemon.Speciality,
IsVariation = NewPokemon.IsVariation,
VariationName = NewPokemon.VariationName,
PokemonImageUrl = NewPokemon.PokemonImageUrl,
PokemonShinyImageUrl = NewPokemon.PokemonShinyImageUrl,
FlavorText = NewPokemon.FlavorText,
Ingredient1 = NewPokemon.Ingredient1,
Ingredient2 = NewPokemon.Ingredient2,
Ingredient3 = NewPokemon.Ingredient3
};
await OnPokemonReady.InvokeAsync(copy);
formChanged = false;
}
else
{
// Optionally send a copy to avoid later mutation by the child
var edit = new Pokemon
{
Id = PokemonToEditId,
PokemonId = PokemonToEdit.PokemonId,
PokemonName = PokemonToEdit.PokemonName,
PokemonType = PokemonToEdit.PokemonType,
SleepType = PokemonToEdit.SleepType,
Speciality = PokemonToEdit.Speciality,
IsVariation = PokemonToEdit.IsVariation,
VariationName = PokemonToEdit.VariationName,
PokemonImageUrl = PokemonToEdit.PokemonImageUrl,
PokemonShinyImageUrl = PokemonToEdit.PokemonShinyImageUrl,
FlavorText = PokemonToEdit.FlavorText,
Ingredient1 = PokemonToEdit.Ingredient1,
Ingredient2 = PokemonToEdit.Ingredient2,
Ingredient3 = PokemonToEdit.Ingredient3
};
await OnPokemonReady.InvokeAsync(edit);
Console.WriteLine(edit);
}
}
}
}

View File

@ -1,25 +0,0 @@

$display-font-sizes: (
1: 5rem,
2: 4.5rem,
3: 4rem,
4: 3.5rem,
5: 3rem,
6: 2.5rem
);
.pokemon-form-container {
position: relative;
aspect-ratio: 3 / 4; /* Maintains card shape dynamically */
background-color: var(--bg-color);
border-width: .5rem;
border-style: solid;
border-radius: 5% / 3.5%;
border-color: var(--border-color);
box-shadow: 0 0 10px var(--border-color);
}
.checkbox-styling {
width: 100px;
height: 100px;
}

View File

@ -1,10 +1,19 @@
<!-- Pokemon Navigation Buttons --> 
<div class="mx-auto w-75 top-row row" > <!-- Heading + Buttons -->
<div class="row btn-group d-flex justify-content-end" > <div class="top-row row rounded-bottom-5 w-100 bg-secondary border-bottom border-start border-end border-2 border-primary py-3">
<div class="col-4"></div>
<div class="col-4 text-center">
<h1 class="text-primary">Pokémon Sleep</h1>
</div>
<div class="col-4">
<div class="btn-group d-flex justify-content-end my-1">
<!-- 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="/pokemon-sleep"> <NavLink href="/pokemonsleep">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-fill mb-1 text-white" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-fill mb-1" 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>
@ -13,8 +22,8 @@
<!-- 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-sleep/pokemon"> <NavLink href="/pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-table mb-1 text-white" viewBox="0 0 16 16"> <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" /> <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>
@ -22,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="/pokemon-sleep/rate-pokemon"> <NavLink href="/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-award-fill mb-1 text-white" viewBox="0 0 16 16"> <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">
<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>
@ -32,8 +41,8 @@
<!-- 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="/pokemon-sleep/add-new-pokemon"> <NavLink href="/pokemonsleep/add-new-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle-fill text-white" 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 mb-1" 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>
@ -41,3 +50,5 @@
</div> </div>
</div> </div>
</div>

View File

@ -1,22 +0,0 @@
<div class="wrapper">
@if (shinyUrl == null)
{
<div class="flip-container">
<div class="flipper">
<img class="front" src="@baseUrl" />
</div>
</div>
}
else
{
<div class="flip-container" @onclick="() => ToggleImage()">
<div class="flipper @(isShiny ? "flipped" : "")">
<img class="front" src="@baseUrl" />
<img class="back" src="@shinyUrl" />
</div>
</div>
}
</div>

View File

@ -1,20 +0,0 @@
using Microsoft.AspNetCore.Components;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonImage
{
[Parameter]
public string baseUrl { get; set; }
[Parameter]
public string shinyUrl { get; set; }
private bool isShiny = false;
private void ToggleImage()
{
isShiny = !isShiny;
StateHasChanged();
}
}
}

View File

@ -1,50 +0,0 @@
.wrapper {
display: inline-block;
width: 90%;
height: 90%;
}
.flip-container {
position: absolute !important;
top: 40% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
perspective: 1000px;
display: inline-block;
width: 80%;
aspect-ratio: 1 / 1;
max-width: 280px;
margin: 0 auto;
cursor: pointer;
}
.flipper {
transition: transform 0.6s;
transform-style: preserve-3d;
width: 100%;
height: 100%;
position: relative;
}
.flipped {
transform: rotateY(180deg);
}
.wrapper {
position: relative;
max-height: 100px;
width: 100%;
}
.front, .back {
width: 100%;
height: 100%;
position: absolute;
inset: 0; /* shorthand for top/right/bottom/left: 0 */
backface-visibility: hidden;
object-fit: contain; /* keep aspect ratio inside the box */
}
.back {
transform: rotateY(180deg);
}

View File

@ -1,6 +0,0 @@
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonNavMenu
{
}
}

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,23 +0,0 @@

<!-- Search Input -->
<div class="pokemon-selector p-3 bg-light">
<input class="form-control mb-3 rounded rounded-5" placeholder="Search Pokémon..." @bind="SearchTerm" @oninput="HandleSearch" />
<!-- Scrollable Pokémon Grid -->
<div class="row pokemon-grid pt-1">
@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") rounded rounded-3"
@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>

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,33 +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;
align-content: flex-start;
}
.pokemon-card {
cursor: pointer;
transition: transform 0.15s ease-in-out;
}
.pokemon-card:hover {
transform: scale(1.13);
}
.small-card {
font-size: 0.75rem;
}

View File

@ -5,54 +5,33 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<!-- Table A: Desktop View--> <!-- Table A: Desktop View-->
<div class="container d-none d-lg-block d-md-none mt-4"> <div class="container d-none d-md-block">
<!-- Main UI --> <!-- Main UI -->
<div class="border-0 mx-auto col-8 "> <div class="card shadow-sm border-0 mt-4 mx-auto col-12 col-md-10 col-lg-8">
<!-- UI Header --> <!-- Table Header -->
<div class="row bg-secondary py-3 border-0 rounded-top"> <div class="row card-header bg-secondary bg-gradient ml-0 py-3 border-0">
<div class="d-flex align-items-center justify-content-between w-100 position-relative px-3"> <div class="flex-row justify-content-between">
<div class="text-center position-relative">
<!-- Left: Search --> <h2 class="text-info text-decoration-underline">Available Pokémon</h2>
<input class="form-control w-25 me-3 rounded rounded-5" <div class="m-1 badge bg-info position-absolute top-0 end-0 border-0"><p class="statText">@(pokemons.Count()) Pokemon</p></div>
placeholder="Search Pokémon..."
@bind="SearchTerm"
@oninput="HandleSearch" />
<!-- Center: Title -->
<h2 class="text-white mb-0 position-absolute start-50 translate-middle-x">
Available Pokémon
</h2>
<!-- Right: Count + Download -->
<div class="d-flex align-items-center gap-2">
<div class="badge bg-light">
<p class="statText text-primary fw-medium shadow mb-0">@(pokemons.Count()) Pokémon</p>
</div> </div>
<PokemonDownloadButton _Pokemon="pokemons" />
</div>
</div> </div>
</div> </div>
<!-- Table -->
<div class="tableFixHead d-flex flex-column justify-content-start bg-secondary table-responsive row "> <div class="tableFixHead table-responsive row">
<table class="table table-borderless border-0 table-secondary table-striped align-middle"> <table class="table col table-borderless border-0 table-secondary table-striped align-middle">
<!-- Table Head --> <!-- Table Head -->
<thead> <thead class="">
<tr> <tr class="">
<th class="text-white text-bg-info col-2" scope="col"></th> <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-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-1 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-1 text-center" scope="col">Speciality</th> <th class="text-white text-bg-info col-2 text-center" scope="col">Speciality</th>
@if (adminToggle)
{
<th class="text-white text-bg-info col-2 text-center" scope="col">Admin</th>
}
</tr> </tr>
</thead> </thead>
<!-- If/Else Pokemon Loaded--> <!-- If/Else Pokemon Loaded-->
@ -66,223 +45,68 @@
{ {
<!-- Table Body --> <!-- Table Body -->
<tbody> <tbody>
@if (FilteredPokemon != null && FilteredPokemon.Any()) @foreach (var pokemon in pokemons)
{ {
@foreach (var pokemon in FilteredPokemon) <tr class="flex-row">
<!-- Section: Pokemon Image -->
@{
string baseUrl = pokemon.PokemonImageUrl;
string shinyUrl = pokemon.PokemonShinyImageUrl;
}
<td class="text-center d-none d-md-table-cell">
@if (shinyUrl == null)
{ {
<tr> <div class="flip-container">
<!-- Section 1: Pokemon Image --> <div class="flipper">
<td class="pokeimage"> <img class="front img-fluid" style="max-width: 100px;" src="@baseUrl" />
<PokemonImage baseUrl="@pokemon.PokemonImageUrl" shinyUrl="@pokemon.PokemonShinyImageUrl" /> </div>
</div>
}
else
{
<div class="flip-container" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" style="max-width: 100px;" src="@baseUrl" />
<img class="back img-fluid" style="max-width: 100px;" src="@shinyUrl" />
</div>
</div>
}
</td> </td>
<!-- Section 2: Pokemon # --> <!-- Section 2: Pokemon # -->
<th scope="row" style="cursor: default;">@pokemon.PokemonId</th> <th class="" scope="row" style="cursor: default;">@pokemon.PokemonId</th>
<!-- Section 3: Pokemon Name --> <!-- Section 3: Pokemon Name -->
<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> <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>
<!-- Section 4: Pokemon Type --> <!-- Section 4: Pokemon Type -->
<td>
<div class="d-flex justify-content-center">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:36px; height:36px;box-shadow: 0 1px 2px 1px rgba(0,0,0,0.35);border-radius: 20px;" />
</div>
</td>
<!-- Section 5: Sleep Type -->
<td>
<div class="d-flex justify-content-center ">
<PokemonBadge BadgeItem="@pokemon.SleepType" />
</div>
</td>
<!-- Section 6: Speciality -->
<td>
<div class="d-flex justify-content-center">
<PokemonBadge BadgeItem="@pokemon.Speciality" />
</div>
</td>
<!-- Section 7: Admin Controls -->
@if (adminToggle)
{
<td>
<div class="d-flex justify-content-center gap-1">
<PokemonEditButton PokemonId="@pokemon.PokemonId" />
<button class="btn btn-danger rounded rounded-5 text-white " @onclick="() => ConfirmDelete(pokemon.Id)">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3-fill" viewBox="0 0 16 16">
<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" />
</svg>
</button>
</div>
</td>
}
</tr>
}
}
else
{
<tr>
<td colspan="100%">
<div class="d-flex justify-content-center align-items-center" style="height: 200px;">
<p class="text-muted">Pokémon could not be found.</p>
</div>
</td>
</tr>
}
</tbody>
}
</table>
</div>
<!-- Wrap in Auth -->
<div class="d-flex justify-content-end mt-1">
<div class="form-check form-switch">
<input class="form-check-input rounded rounded-3" type="checkbox" role="switch" id="flexSwitchCheckDefault" @bind="adminToggle">
</div>
</div>
</div>
</div>
<div class="container d-none d-lg-none d-md-block mt-4">
<!-- Main UI -->
<div class="border-0 mx-auto col-8 ">
<!-- UI Header -->
<div class="row bg-secondary py-3 border-0 rounded-top">
<div class="d-flex flex-row align-items-center justify-content-between w-100 gap-3 ms-0 me-0">
<div class="col">
<input class="form-control rounded rounded-5 fs-6 fw-lighter"
placeholder="Search Pokémon..."
@bind="SearchTerm"
@oninput="HandleSearch" />
</div>
<!-- Left: Search -->
<!-- Center: Title -->
<div class="col">
<h2 class="text-white text-center pt-2 fs-6 fw-light">
Available Pokémon
</h2>
</div>
<!-- Right: Count + Download -->
<div class="col">
<div class="d-flex align-items-center gap-1">
<div class="badge bg-light">
<p class="statText text-primary fw-medium shadow mb-0">@(pokemons.Count()) Pokémon</p>
</div>
<PokemonDownloadButton _Pokemon="pokemons" />
</div>
</div>
</div>
</div>
<!-- Table -->
<div class="tableFixHead d-flex flex-column justify-content-start bg-secondary table-responsive row ">
<table class="table table-borderless border-0 table-secondary table-striped align-middle">
<!-- Table Head -->
<thead>
<tr>
<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-2" scope="col">Pokémon</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">Sleep Type</th>
<th class="text-white text-bg-info col-1 text-center" scope="col">Speciality</th>
@if (adminToggle)
{
<th class="text-white text-bg-info col-2 text-center" scope="col">Admin</th>
}
</tr>
</thead>
<!-- If/Else Pokemon Loaded-->
@if (pokemons == null)
{
<tbody>
<Loading />
</tbody>
}
else
{
<!-- Table Body -->
<tbody>
@if (FilteredPokemon != null && FilteredPokemon.Any())
{
@foreach (var pokemon in FilteredPokemon)
{
<tr>
<!-- Section 1: Pokemon Image -->
<td class=""> <td class="">
<img src="@pokemon.PokemonImageUrl" style="width:100px;" />
</td>
<!-- Section 2: Pokemon # -->
<th scope="row" style="cursor: default;">@pokemon.PokemonId</th>
<!-- Section 3: Pokemon Name -->
<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>
<!-- Section 4: Pokemon Type -->
<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> <td class="" style="">
<div class="d-flex justify-content-center "> <div class="d-flex justify-content-center ">
<PokemonBadge BadgeItem="@pokemon.SleepType" /> <PokemonBadge BadgeItem="@pokemon.SleepType" />
</div> </div>
</td> </td>
<!-- Section 6: Speciality --> <!-- Section 6: Speciality -->
<td> <td class="" style="">
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<PokemonBadge BadgeItem="@pokemon.Speciality" /> <PokemonBadge BadgeItem="@pokemon.Speciality" />
</div> </div>
</td> </td>
<!-- Section 7: Admin Controls -->
@if (adminToggle)
{
<td>
<div class="d-flex justify-content-center gap-1">
<PokemonEditButton PokemonId="@pokemon.PokemonId" />
<button class="btn btn-danger rounded rounded-5 text-white " @onclick="() => ConfirmDelete(pokemon.Id)">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3-fill" viewBox="0 0 16 16">
<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" />
</svg>
</button>
</div>
</td>
}
</tr>
}
}
else
{
<tr>
<td colspan="100%">
<div class="d-flex justify-content-center align-items-center" style="height: 200px;">
<p class="text-muted">Pokémon could not be found.</p>
</div>
</td>
</tr> </tr>
} }
</tbody> </tbody>
@ -290,28 +114,21 @@
</table> </table>
</div>
<!-- Wrap in Auth -->
<div class="d-flex justify-content-end mt-1">
<div class="form-check form-switch">
<input class="form-check-input rounded rounded-3" type="checkbox" role="switch" id="flexSwitchCheckDefault" @bind="adminToggle">
</div>
</div>
</div>
</div> </div>
</div>
</div>
<!-- Desktop B: Mobile View --> <!-- Desktop B: Mobile View -->
@* <div class="container card border-0 d-block d-md-none mx-auto mt-4 shadow-sm"> <div class="container card border-0 d-block d-md-none mx-auto mt-4 shadow-sm">
<!-- Table Header --> <!-- Table Header -->
<div class="row card-header bg-secondary bg-gradient ml-0 py-3 border-0 bg-info"> <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="flex-row justify-content-between">
<div class="text-center position-relative"> <div class="text-center position-relative">
<h2 class="text-white text-decoration-underline">Pokémon</h2> <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 class="m-1 badge bg-white text-info position-absolute top-0 end-0 border-0 w-auto"><p class="statText">@(pokemons.Count())</p></div>
</div> </div>
</div> </div>
</div> </div>
@ -331,10 +148,10 @@
@foreach (var pokemon in pokemons) @foreach (var pokemon in pokemons)
{ {
<tr class="border-0"> <tr class="border-0">
<div class="d-flex align-items-center" style="border: 1px dashed hotpink;"> <div class="d-flex align-items-center">
<!-- Pokemon Image --> <!-- Pokemon Image -->
<div class="me-3" style="border: 1px dashed hotpink;"> <div class="me-3">
<div class="flip-container-sm" @onclick="() => ToggleImage(pokemon.Id)"> <div class="flip-container-sm" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper-sm @(isShiny[pokemon.Id] ? "flipped" : "")"> <div class="flipper-sm @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" src="@pokemon.PokemonImageUrl" /> <img class="front img-fluid" src="@pokemon.PokemonImageUrl" />
@ -346,7 +163,7 @@
</div> </div>
</div> </div>
<div style="border: 1px dashed hotpink;"> <div>
<!-- Number and Name --> <!-- Number and Name -->
<h5> <h5>
@pokemon.PokemonId - @pokemon.PokemonId -
@ -357,8 +174,8 @@
<!-- Stats --> <!-- Stats -->
<div class="d-flex flex-wrap align-items-center gap-2"> <div class="d-flex flex-wrap align-items-center gap-2">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:28px;" /> <img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:28px;" />
<PokemonBadge BadgeItem="@pokemon.SleepType" /> <div class=" badge @pokemon.SleepType.ToLower() border-0"><p class="statText">@pokemon.SleepType</p></div>
<PokemonBadge BadgeItem="@pokemon.Speciality" /> <div class=" badge @pokemon.Speciality.ToLower() border-0"><p class="statText">@pokemon.Speciality</p></div>
</div> </div>
</div> </div>
@ -369,4 +186,4 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div> *@ </div>

View File

@ -2,7 +2,6 @@
using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using Portfolio.Domain.Features.Pokemon; using Portfolio.Domain.Features.Pokemon;
using System.Text.Json;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{ {
@ -12,8 +11,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
public List<Pokemon> AllPokemon { get; set; } public List<Pokemon> AllPokemon { get; set; }
private List<Pokemon> pokemons = new List<Pokemon>(); private List<Pokemon> pokemons = new List<Pokemon>();
private Dictionary<int, bool> isShiny = new Dictionary<int, bool>();
private bool adminToggle = false;
protected override void OnParametersSet() protected override void OnParametersSet()
@ -21,19 +19,19 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
if (AllPokemon != null) { if (AllPokemon != null) {
pokemons = AllPokemon.ToList(); pokemons = AllPokemon.ToList();
} foreach (var pokemon in pokemons)
}
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() ?? ""; isShiny[pokemon.Id] = false;
}
}
}
private void ToggleImage(int Id)
{
if (isShiny.ContainsKey(Id))
{
isShiny[Id] = !isShiny[Id];
}
} }
private bool ToggleVariationName(int Id, int PokemonId) private bool ToggleVariationName(int Id, int PokemonId)
@ -66,12 +64,12 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
private void EditPokemon(int id) private void EditPokemon(int id)
{ {
Navigation.NavigateTo($"/pokemon-sleep/edit/{id}"); Navigation.NavigateTo($"/pokemonsleep/edit/{id}");
} }
private void ViewPokemon(int id) private void ViewPokemon(int id)
{ {
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{id}"); Navigation.NavigateTo($"/pokemon/{id}");
} }
private string GetTypeImageUrl(string pokemonType) private string GetTypeImageUrl(string pokemonType)
@ -84,9 +82,5 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
return $"https://www.serebii.net/pokemonsleep/pokemon/type/{pokemonType.ToLower()}.png"; return $"https://www.serebii.net/pokemonsleep/pokemon/type/{pokemonType.ToLower()}.png";
} }
private void HandleToggleChange(ChangeEventArgs e)
{
Console.WriteLine($"Admin Toggle is now: {adminToggle}");
}
} }
} }

View File

@ -1,15 +1,10 @@
.five-percent { .five-percent {
width: 5%; width: 5%;
} }
.ten-percent { .ten-percent {
width: 10%; width: 10%;
} }
.pokemontable {
height: 65vh;
}
.tableFixHead { .tableFixHead {
overflow: auto; overflow: auto;
height: 600px; height: 600px;
@ -21,10 +16,6 @@
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; font-size: 1.3rem;
@ -83,8 +74,28 @@
transform: rotateY(180deg); transform: rotateY(180deg);
} }
.fixed-row-height {
height: 90px; /* or any height that suits your card style */
.pokeimage {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.front, .back {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
}
.back {
transform: rotateY(180deg);
} }
@ -108,15 +119,5 @@
cursor: default; cursor: default;
} }
.pokeimage {
width: 100px;
height: 130px;
}

View File

@ -1,34 +0,0 @@
<div class=" mx-auto w-75" >
<header class="pt-5 w-100">
<div class="row flex-nowrap justify-content-evenly align-items-center" >
<div class="col pt-1">
<div class="d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="@_primaryColor" 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-2 text-primary">Kira Jiroux</span>
</div>
</div>
<div class="col d-flex justify-content-end align-items-center gap-5">
<NavLink class="nav-link d-flex align-items-center rounded rounded-5" href="" Match="NavLinkMatch.All" ActiveClass="nav-active">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="@_primaryColor" class="bi bi-house-heart-fill" viewBox="0 0 16 16">
<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 text-primary">Home</span>
</NavLink>
<NavLink class="nav-link d-flex align-items-center rounded rounded-5" href="temperature-blanket" ActiveClass="nav-active">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="@_primaryColor" class="bi bi-grid-3x3" viewBox="0 0 16 16">
<path d="M0 1.5A1.5 1.5 0 0 1 1.5 0h13A1.5 1.5 0 0 1 16 1.5v13a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 0 14.5zM1.5 1a.5.5 0 0 0-.5.5V5h4V1zM5 6H1v4h4zm1 4h4V6H6zm-1 1H1v3.5a.5.5 0 0 0 .5.5H5zm1 0v4h4v-4zm5 0v4h3.5a.5.5 0 0 0 .5-.5V11zm0-1h4V6h-4zm0-5h4V1.5a.5.5 0 0 0-.5-.5H11zm-1 0V1H6v4z" />
</svg><span class="mx-2 mt-0 text-primary">Crochet</span>
</NavLink>
<NavLink class="nav-link d-flex align-items-center rounded rounded-5" href="pokemon-sleep" ActiveClass="nav-active">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="@_primaryColor" 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> <span class="mx-2 mt-0 text-primary">Pokémon Sleep</span>
</NavLink>
</div>
</div>
</header>
</div>
<div class="mt-2 mb-3 mx-auto w-75 border-top border-primary-subtle"></div>

View File

@ -1,7 +0,0 @@
namespace Portfolio.WebUI.Server.Components.Layout
{
public partial class BaseNavMenu
{
private string _primaryColor = "#593196";
}
}

View File

@ -1,13 +0,0 @@
body {
}
::deep .nav-active {
font-weight: bold;
background-color: #f2eaff;
color: black;
padding-left: 15px;
padding-right: 15px;
padding-top: 5px;
padding-bottom: 5px;
border: 1px dashed #593196;
}

View File

@ -1,14 +0,0 @@

<div class="mt-2 mx-auto w-75 mt-2 border-top border-primary-subtle"></div>
<div class="container mt-2">
<footer class="d-flex flex-column align-content-center">
<p class="text-center fs-6 fw-lighter text-muted">
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,9 +1,12 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<div class="d-flex flex-column min-vh-100"> <div class="page bg-primary-subtle ">
<BaseNavMenu />
<main class="container flex-grow-1"> <Sidebar/>
<main class="border border-3 border-dark w-100">
<article class="container border border-3 border-black px-4 w-100 m-auto">
@Body @Body
</article>
</main> </main>
<MadeWithLoveFooter/>
</div> </div>

View File

@ -1,4 +1,8 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main { main {
flex: 1; flex: 1;
@ -8,10 +12,6 @@ main {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
} }
.container {
max-width: 1920px;
}
.top-row { .top-row {
background-color: #f7f7f7; background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5; border-bottom: 1px solid #d6d5d5;
@ -47,6 +47,9 @@ main {
} }
@media (min-width: 641px) { @media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar { .sidebar {
width: 250px; width: 250px;
@ -73,3 +76,21 @@ main {
} }
} }
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}

View File

@ -1,35 +1,35 @@
<div class="navbar navbar-expand bg-primary border-0"> <div class="top-row ps-3 navbar navbar-dark">
<div class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-light text-decoration-none px-3"> <div class="container-fluid">
<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;"> <a class="navbar-brand" href="">Portfolio.WebUI.Server</a>
<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" /> </div>
</svg>
<span class="fs-4 mx-2 text-white">Kira Jiroux</span>
</div> </div>
<ul class="navbar-nav">
<li class="nav-item"> <input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<NavLink class="nav-link d-flex align-items-center" href="" Match="NavLinkMatch.All">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFFFFF" class="bi bi-house-heart-fill" viewBox="0 0 16 16"> <div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<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" /> <nav class="flex-column">
<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" /> <div class="nav-item px-3">
</svg> <span class="mx-2 mt-0 text-white">Home</span> <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink> </NavLink>
</li> </div>
<li>
<NavLink class="nav-link d-flex align-items-center" href="temperature-blanket"> <div class="nav-item px-3">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFFFFF" class="bi bi-border-outer" viewBox="0 0 16 16"> <NavLink class="nav-link" href="articles">
<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" /> <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="M0 0v16h16V0zm1 1h14v14H1z" /> <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" />
</svg><span class="mx-2 mt-0 text-white">Crochet</span> <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" />
<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> </div>
<li> <div class="nav-item px-3">
<NavLink class="nav-link d-flex align-items-center" href="pokemonsleep"> <NavLink class="nav-link" href="pokemonsleep">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFFFFF" 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 text-white">Pokémon Sleep</span> </svg> Pokemon Sleep
</NavLink> </NavLink>
</li>
</ul>
</div> </div>
</nav>
</div>

View File

@ -0,0 +1,105 @@
.navbar-toggler {
appearance: none;
cursor: pointer;
width: 3.5rem;
height: 2.5rem;
color: white;
position: absolute;
top: 0.5rem;
right: 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}
.navbar-toggler:checked {
background-color: rgba(255, 255, 255, 0.5);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}
.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}
.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}
.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep .nav-link {
color: #d7d7d7;
background: none;
border: none;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
width: 100%;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}
.nav-item ::deep .nav-link:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
.nav-scrollable {
display: none;
}
.navbar-toggler:checked ~ .nav-scrollable {
display: block;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.nav-scrollable {
/* Never collapse the sidebar for wide screens */
display: block;
/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}

View File

@ -0,0 +1,41 @@
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="articles">
<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 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="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" />
<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>
</li>
<li class="nav-item">
<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">
<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 class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</div>
</nav>

View File

@ -0,0 +1,45 @@
<div class="navbar navbar-expand-lg navbar-light bg-info justify-content-md-center" id="navbarsExample08">
<ul class="navbar-nav">
<li class="nav-item">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Kira Jiroux
</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="articles">
<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 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="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" />
<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>
</li>
<li class="nav-item">
<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">
<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 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>
</div>

View File

@ -3,12 +3,7 @@
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<PageTitle>Crochet Tools</PageTitle> <h3 class="text-xl font-bold mb-4">Crochet</h3>
@* <h3 class="text-xl font-bold mb-4">Crochet</h3> *@
<div class="">
<TemperatureBlanketVisualizer TemperatureDays="temperatureDays" /> <TemperatureBlanketVisualizer TemperatureDays="temperatureDays" />
</div>

View File

@ -9,60 +9,19 @@ namespace Portfolio.WebUI.Server.Components.Pages.Crochet_Pages
public partial class CrochetHome public partial class CrochetHome
{ {
public List<TemperatureDay> temperatureDays { get; set; } public List<TemperatureDay> temperatureDays { get; set; }
public int YEAR = 2025;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
// Placeholder for loading temperature data // Placeholder for loading temperature data
// Replace with actual API call // Replace with actual API call
//temperatureDays = Enumerable.Range(0, 365).Select(i => new TemperatureDay 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>(); Date = new DateTime(DateTime.Now.Year - 1, 1, 1).AddDays(i),
var startDate = new DateTime(year, 1, 1); AvgTemp = Random.Shared.Next(10, 95)
int daysInYear = DateTime.IsLeapYear(year) ? 366 : 365; }).ToList();
// 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,841 +1,9 @@
@page "/" @page "/"
@inject IHttpClientFactory ClientFactory
@attribute [StreamRendering]
@rendermode InteractiveServer
<PageTitle>Home</PageTitle> <PageTitle>Home</PageTitle>
<!-- View 1: Desktop View --> <!-- <PokemonBackground />-->
<div class="container d-none d-lg-none d-xl-block mt-3 pt-3 pb-5 ps-5 pe-5 "> <h1 class="test">Hello, world!</h1>
<h1 class="fst-italic fw-light fs-1 font-monospace">Hello, World!</h1> <p>Ensuring that git is connected properly.</p>
<!-- Start of Grid -->
<div class="row mb-3">
<!-- Profile Image -->
<div class="col-auto ">
<img class="card-img rounded-3" style="width: 18.1em;" src="https://i.pinimg.com/736x/54/63/ed/5463ed9471053712a76c0dd0b301a7ea.jpg" />
</div>
<div class="col ">
<!-- About Me-->
<div class="d-inline-flex row card rounded fs-5 mb-3 p-2 ps-3 pe-3 border-0">
I am a full-stack web developer with additional
experience in Data Analysis and Visualization, as well as
Simulation/VR development, and AI/ML programming.
I am a friendly team worker with strong analytical, math
and problem-solving skills that adapts well to an
Agile/SCRUM environment and development lifecycle.
</div>
<div class="row">
<!-- School Experience -->
<div class="col ps-0">
<div class="card rounded p-2 ps-3 pe-3 border border-1 border-primary">
<p class="fs-6 fw-lighter card-subtitle p-0">September 2018 March 2022</p>
<p class="fs-5 card-title m-0">B.S. in Computer Science</p>
<p class="fs-6 fw-lighter card-subtitle">Oregon State University</p>
<p class="fs-6 fw-lighter card-subtitle">Graduated Cum Laude</p>
<p class="fs-6 fw-lighter card-subtitle">Deans List: Fall 2020, Fall 2021</p>
<p class="fs-6 fw-lighter card-subtitle">Final GPA: 3.33</p>
@**@
<!-- Courses -->
<label class="text-decoration-underline fw-semibold">Courses</label>
<div class="overflow-auto" style="height: auto; max-height: 12rem">
<ul class="list-group list-group-flush">
@if (courses == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var course in courses)
{
<li class="list-group-item">@course</li>
}
</ul>
}
</ul>
</div>
</div>
@* <div class="ps-3 pe-3">
<ul class="list-group list-group-flush">
<li class="">Organized</li>
<li class="">Responsible</li>
<li class="">Meticulous</li>
<li class="">Analytical</li>
<li class="">Self-motivating</li>
</ul>
</div> *@
</div>
<!--Skills \ Languages-->
<div class="col-auto p-0 ">
<div class="bg-white rounded p-2 border border-1 border-primary" >
<div class="card-header">
<label class="text-decoration-underline fw-semibold">Skills \ Languages</label>
</div>
<div class="overflow-auto" style="max-height: 20.1rem">
@if (skills == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var skill in skills)
{
<li class="list-group-item">@skill</li>
}
</ul>
}
</div>
</div>
</div>
<!-- Tools -->
<div class="col-auto pe-0">
<div class="bg-white rounded p-2 border border-1 border-primary">
<div class="card-header">
<label class="text-decoration-underline fw-semibold">Tools</label>
</div>
<div class="overflow-auto" style="max-height: 20.1rem">
@if (tools == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var tool in tools)
{
<li class="list-group-item">@tool</li>
}
</ul>
}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Experiences / Projects -->
<div class="row ">
<div class="col card border-0 rounded rounded-4 pt-3 pb-3">
<!-- Button Bay-->
<div class="row mt-2">
<div class="d-grid gap-2 d-md-flex justify-content-around">
<button class="btn rounded-4 w-25 @(isExperience ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleExperience()">Experience</button>
<button class="btn rounded-4 w-25 @(isProjects ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleProjects()">Projects</button>
</div>
</div>
<div class="row">
<div class="col">
@if (isExperience)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">
Experience
</div>
@if (experiences == null)
{
<div>Loading...</div>
}
else
{
@foreach (var experience in experiences)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-6 fw-lighter card-subtitle p-0"> @experience.StartYear @experience.EndYear</p>
<p class="fs-5 card-title m-0">@experience.Title - @experience.Company</p>
<p class="fs-6 fw-lighter card-text">@experience.Details</p>
</div>
</div>
}
}
}
else if (isProjects)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">Projects</div>
@if (projects == null)
{
<p>Loading projects...</p>
}
else
{
@foreach (var project in projects)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-5 card-title m-0">@project.Title</p>
@foreach (var desc in project.Descriptions)
{
<p class="fs-6 fw-lighter card-text">@((MarkupString)FormatDescription(desc))</p>
}
@if (project.Links?.Any() == true)
{
<div class="mt-2 align-self-end">
@foreach (var link in project.Links)
{
@switch (link.Type)
{
case "external":
<a class="me-2" href="@link.Url">@link.Label</a>
break;
case "internal":
<a class="mt-2 " href=""@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-code" viewBox="0 0 16 16">
<path d="M6.646 5.646a.5.5 0 1 1 .708.708L5.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708zm2.708 0a.5.5 0 1 0-.708.708L10.293 8 8.646 9.646a.5.5 0 0 0 .708.708l2-2a.5.5 0 0 0 0-.708z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1"/>
</svg>
</a>
break;
case "github":
<a class="mt-2" href="@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a>
break;
}
}
</div>
}
</div>
</div>
}
}
}
</div>
</div>
</div>
</div>
</div>
<!-- View 2: Smaller Desktop View -->
<div class="container d-none d-md-none d-xl-none d-lg-block mt-4 pt-3 pb-4 ">
<div class="row">
<h1 class="fst-italic fw-light fs-1 font-monospace ps-1">Hello, World!</h1>
</div>
<div class="row mb-3">
<div class="col-auto ps-0">
<img class="card-img rounded-3" style="width: 16.9em;" src="https://i.pinimg.com/736x/54/63/ed/5463ed9471053712a76c0dd0b301a7ea.jpg" />
</div>
<div class="col ">
<!-- About Me-->
<div class="row card rounded fs-6 mb-3 p-2 ps-3 pe-3 border-0">
I am a full-stack web developer with additional
experience in Data Analysis and Visualization, as well as
Simulation/VR development, and AI/ML programming.
I am a friendly team worker with strong analytical, math
and problem-solving skills that adapts well to an
Agile/SCRUM environment and development lifecycle.
</div>
<div class="row mt-3">
<!-- School Experience -->
<div class="col me-1">
<div class="row bg-white rounded p-2 ps-3 pe-3 border border-1 border-primary">
<p class="fs-6 fw-lighter card-subtitle p-0">September 2018 March 2022</p>
<p class="fs-5 card-title m-0 p-0">B.S. in Computer Science</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Oregon State University</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Graduated Cum Laude</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Deans List: Fall 2020, Fall 2021</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Final GPA: 3.33</p>
<!-- Courses -->
<label class="text-decoration-underline p-0">Courses</label>
<div class="overflow-auto p-0" style="max-height: 10rem">
<ul class="list-group list-group-flush">
@if (courses == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var course in courses)
{
<li class="list-group-item">@course</li>
}
</ul>
}
</ul>
</div>
</div>
</div>
<div class="col ms-1">
<!--Skills \ Languages-->
<div class="row bg-white rounded p-2 border border-1 border-primary mb-2">
<div class="card-header">
<label class="text-decoration-underline">Skills \ Languages</label>
</div>
<div class="overflow-auto p-0" style="max-height: 8rem">
@if (skills == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var skill in skills)
{
<li class="list-group-item">@skill</li>
}
</ul>
}
</div>
</div>
<!-- Tools -->
<div class="row bg-white rounded p-2 border border-1 border-primary">
<div class="card-header">
<label class="text-decoration-underline">Tools</label>
</div>
<div class="overflow-auto p-0" style="max-height: 8rem">
@if (tools == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var tool in tools)
{
<li class="list-group-item">@tool</li>
}
</ul>
}
</div>
</div>
</div>
</div>
</div>
<!-- Experience / Projects -->
<div>
<div class="row mt-3">
<div class="col card border-0 rounded rounded-4 pt-3 pb-3">
<!-- Button Bay-->
<div class="row mt-2">
<div class="d-grid gap-2 d-md-flex justify-content-around">
<button class="btn rounded-4 w-25 @(isExperience ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleExperience()">Experience</button>
<button class="btn rounded-4 w-25 @(isProjects ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleProjects()">Projects</button>
</div>
</div>
<div class="row">
<div class="col">
@if (isExperience)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">
Experience
</div>
@if (experiences == null)
{
<div>Loading...</div>
}
else
{
@foreach (var experience in experiences)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-6 fw-lighter card-subtitle p-0"> @experience.StartYear @experience.EndYear</p>
<p class="fs-5 card-title m-0">@experience.Title - @experience.Company</p>
<p class="fs-6 fw-lighter card-text">@experience.Details</p>
</div>
</div>
}
}
}
else if (isProjects)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">Projects</div>
@if (projects == null)
{
<p>Loading projects...</p>
}
else
{
@foreach (var project in projects)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-5 card-title m-0">@project.Title</p>
@foreach (var desc in project.Descriptions)
{
<p class="fs-6 fw-lighter card-text">@((MarkupString)FormatDescription(desc))</p>
}
@if (project.Links?.Any() == true)
{
<div class="mt-2 align-self-end">
@foreach (var link in project.Links)
{
@switch (link.Type)
{
case "external":
<a class="me-2" href="@link.Url">@link.Label</a>
break;
case "internal":
<a class="mt-2 " href=""@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-code" viewBox="0 0 16 16">
<path d="M6.646 5.646a.5.5 0 1 1 .708.708L5.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708zm2.708 0a.5.5 0 1 0-.708.708L10.293 8 8.646 9.646a.5.5 0 0 0 .708.708l2-2a.5.5 0 0 0 0-.708z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1"/>
</svg>
</a>
break;
case "github":
<a class="mt-2" href="@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a>
break;
}
}
</div>
}
</div>
</div>
}
}
}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- View 3: Tablet View -->
<div class="container d-none d-md-block d-lg-none mt-4 pt-3 pb-4 ">
<h1 class="fst-italic fw-light fs-1 font-monospace">Hello, World!</h1>
<div class="row">
<div class="card rounded p-3 border-0">
<div class="clearfix">
<img src="https://i.pinimg.com/736x/54/63/ed/5463ed9471053712a76c0dd0b301a7ea.jpg"
class="mobile-profile float-start me-3 mb-2"
style="width: 10em;
height: 10em;
object-fit: cover;
border-radius: 0.5rem;" />
<p class="fs-6 mb-0">
I am a full-stack web developer with additional experience in Data Analysis and Visualization,
as well as Simulation/ VR development, and AI/ ML programming. I am a friendly team worker with
strong analytical, math and problem-solving skills that adapts well to an Agile/SCRUM environment
and development lifecycle.
</p>
</div>
</div>
</div>
<div class="row mt-3">
<!-- School Experience -->
<div class="col me-1">
<div class="row bg-white rounded p-2 ps-3 pe-3 border border-1 border-primary">
<p class="fs-6 fw-lighter card-subtitle p-0">September 2018 March 2022</p>
<p class="fs-5 card-title m-0 p-0">B.S. in Computer Science</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Oregon State University</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Graduated Cum Laude</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Deans List: Fall 2020, Fall 2021</p>
<p class="fs-6 fw-lighter card-subtitle p-0">Final GPA: 3.33</p>
<!-- Courses -->
<label class="text-decoration-underline p-0">Courses</label>
<div class="overflow-auto p-0" style="max-height: 9.8rem">
<ul class="list-group list-group-flush">
@if (courses == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var course in courses)
{
<li class="list-group-item">@course</li>
}
</ul>
}
</ul>
</div>
</div
</div>
<div class="col ms-1">
<!--Skills \ Languages-->
<div class="row bg-white rounded p-2 border border-1 border-primary mb-2">
<div class="card-header">
<label class="text-decoration-underline">Skills \ Languages</label>
</div>
<div class="overflow-auto p-0" style="max-height: 8rem">
@if (skills == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var skill in skills)
{
<li class="list-group-item">@skill</li>
}
</ul>
}
</div>
</div>
<!-- Tools -->
<div class="row bg-white rounded p-2 border border-1 border-primary">
<div class="card-header">
<label class="text-decoration-underline">Tools</label>
</div>
<div class="overflow-auto p-0" style="max-height: 8rem">
@if (tools == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var tool in tools)
{
<li class="list-group-item">@tool</li>
}
</ul>
}
</div>
</div>
</div>
</div>
<div>
<div class="row mt-3">
<div class="col card border-0 rounded rounded-4 pt-3 pb-3">
<!-- Button Bay-->
<div class="row mt-2">
<div class="d-grid gap-2 d-md-flex justify-content-around">
<button class="btn rounded-4 w-25 @(isExperience ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleExperience()">Experience</button>
<button class="btn rounded-4 w-25 @(isProjects ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleProjects()">Projects</button>
</div>
</div>
<div class="row">
<div class="col">
@if (isExperience)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">
Experience
</div>
@if (experiences == null)
{
<div>Loading...</div>
}
else
{
@foreach (var experience in experiences)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-6 fw-lighter card-subtitle p-0"> @experience.StartYear @experience.EndYear</p>
<p class="fs-5 card-title m-0">@experience.Title - @experience.Company</p>
<p class="fs-6 fw-lighter card-text">@experience.Details</p>
</div>
</div>
}
}
}
else if (isProjects)
{
<div class="row justify-content-md-center fst-italic fs-1 mb-2">Projects</div>
@if (projects == null)
{
<p>Loading projects...</p>
}
else
{
@foreach (var project in projects)
{
<div class="row justify-content-md-center mb-3">
<div class="card w-75 p-3 ps-4 pe-4 rounded">
<p class="fs-5 card-title m-0">@project.Title</p>
@foreach (var desc in project.Descriptions)
{
<p class="fs-6 fw-lighter card-text">@((MarkupString)FormatDescription(desc))</p>
}
@if (project.Links?.Any() == true)
{
<div class="mt-2 align-self-end">
@foreach (var link in project.Links)
{
@switch (link.Type)
{
case "external":
<a class="me-2" href="@link.Url">@link.Label</a>
break;
case "internal":
<a class="mt-2 " href=""@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-code" viewBox="0 0 16 16">
<path d="M6.646 5.646a.5.5 0 1 1 .708.708L5.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708zm2.708 0a.5.5 0 1 0-.708.708L10.293 8 8.646 9.646a.5.5 0 0 0 .708.708l2-2a.5.5 0 0 0 0-.708z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1"/>
</svg>
</a>
break;
case "github":
<a class="mt-2" href="@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a>
break;
}
}
</div>
}
</div>
</div>
}
}
}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- View 4: Mobile View -->
<div class="container card rounded border-0 d-block d-md-none mx-auto mt-4 mb-3">
<h1 class="fst-italic fw-light fs-1 font-monospace pt-2">Hello, World!</h1>
<div class="row">
<div class="card border-0">
<div class="clearfix">
<img src="https://i.pinimg.com/736x/54/63/ed/5463ed9471053712a76c0dd0b301a7ea.jpg"
class="mobile-profile float-start me-3 mb-2" />
<p class="fs-6 mb-0">
I am a full-stack web developer with additional experience in Data Analysis and Visualization,
as well as Simulation/ VR development, and AI/ ML programming. I am a friendly team worker with
strong analytical, math and problem-solving skills that adapts well to an Agile/SCRUM environment
and development lifecycle.
</p>
</div>
</div>
</div>
@* <div class="row mb-3 bg-info rounded rounded-5 pt-1 pb-1">
<p class="fw-lighter fs-6 text-nowrap p-0 m-auto text-center text-white">
Organized • Responsible • Meticulous • Analytical • Self-motivating
</p>
</div> *@
<hr class="text-primary" />
<!-- Education -->
<div class="row mb-3 ms-2 me-2 ">
<div class="card p-2 ps-3 pe-3 border border-1 border-primary rounded rounded-1">
<p class="fs-6 fw-lighter card-subtitle m-0">September 2018 March 2022</p>
<p class="fs-4 card-title m-0">B.S. in Computer Science</p>
<p class="fs-6 fw-lighter card-subtitle">Oregon State University</p>
<p class="fs-6 fw-lighter card-subtitle">Graduated Cum Laude</p>
<p class="fs-6 fw-lighter card-subtitle">Deans List: Fall 2020, Fall 2021</p>
<p class="fs-6 fw-lighter card-subtitle">Final GPA: 3.33</p>
</div>
</div>
<!-- Skills \ Languages -->
<div class="row mb-3 ms-2 me-2">
<div class="bg-primary-subtle rounded p-2 border-0">
<div class="card-header text-bg-primary text-light fs-3">
Skills \ Languages
</div>
<div class="overflow-auto" style="max-height: 15rem">
@if (skills == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var skill in skills)
{
<li class="list-group-item">@skill</li>
}
</ul>
}
</div>
</div>
</div>
<!-- Technology -->
<div class="row mb-3 ms-2 me-2">
<div class="bg-primary-subtle rounded p-2 border-0">
<div class="card-header text-bg-primary text-light fs-3">
Technology
</div>
<div class="overflow-auto" style="max-height: 15rem">
@if (tools == null)
{
<div>Loading...</div>
}
else
{
<ul class="list-group list-group-flush">
@foreach (var tool in tools)
{
<li class="list-group-item">@tool</li>
}
</ul>
}
</div>
</div>
</div>
<!-- Experience \ Projects -->
<div class="row mb-3 ms-2 me-2">
<div class="col card border-0 rounded rounded-4 pt-3 ">
<!-- Button Bay-->
<div class="row mt-2">
<div class="d-flex justify-content-evenly">
<button class="btn rounded-4 flex-fill @(isExperience ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleExperience()">Experience</button>
<button class="btn rounded-4 flex-fill @(isProjects ? "btn-primary" : "btn-outline-primary")" type="button" @onclick="() => ToggleProjects()">Projects</button>
</div>
</div>
@if (isExperience)
{
<div class="row justify-content-center fst-italic fs-1 mt-2">
Experience
</div>
@if (experiences == null)
{
<div>Loading...</div>
}
else
{
<div class="overflow-auto" style="max-height: 16rem">
<ul class="list-group list-group-flush">
@foreach (var experience in experiences)
{
<div class=" justify-content-md-center">
<div class="card p-3 ps-4 pe-4 rounded">
<p class="fs-6 fw-lighter card-subtitle p-0"> @experience.StartYear @experience.EndYear</p>
<p class="fs-5 card-title m-0">@experience.Title - @experience.Company</p>
<p class="fs-6 fw-lighter card-text">@experience.Details</p>
</div>
</div>
}
</ul>
</div>
}
}
else if (isProjects)
{
<div class="row justify-content-center fst-italic fs-1 mt-2">Projects</div>
<div class="overflow-auto" style="max-height: 16rem">
<ul class="list-group list-group-flush">
@foreach (var project in projects)
{
<div class="justify-content-center">
<div class="card p-3 ps-4 pe-4 rounded">
<p class="fs-5 card-title m-0">@project.Title</p>
@foreach (var desc in project.Descriptions)
{
<p class="fs-6 fw-lighter card-text">@((MarkupString)FormatDescription(desc))</p>
}
@if (project.Links?.Any() == true)
{
<div class="mt-2 align-self-end">
@foreach (var link in project.Links)
{
@switch (link.Type)
{
case "external":
<a class="me-2" href="@link.Url">@link.Label</a>
break;
case "internal":
<a class="mt-2 " href=""@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-code" viewBox="0 0 16 16">
<path d="M6.646 5.646a.5.5 0 1 1 .708.708L5.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708zm2.708 0a.5.5 0 1 0-.708.708L10.293 8 8.646 9.646a.5.5 0 0 0 .708.708l2-2a.5.5 0 0 0 0-.708z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1"/>
</svg>
</a>
break;
case "github":
<a class="mt-2" href="@link.Url">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
</svg>
</a>
break;
}
}
</div>
}
</div>
</div>
}
</ul>
</div>
}
</div>
</div>
</div>
Welcome to your new app.

View File

@ -1,53 +0,0 @@
using Portfolio.Domain.Features.Portfolio;
using static System.Net.WebRequestMethods;
namespace Portfolio.WebUI.Server.Components.Pages
{
partial class Home
{
private List<string> skills;
private List<string> tools;
private List<string> courses;
private List<WorkExperience> experiences;
private List<ProjectEntry> projects;
private bool isExperience = true;
private bool isProjects = false;
protected override async Task OnInitializedAsync()
{
var http = ClientFactory.CreateClient("LocalClient");
skills = await http.GetFromJsonAsync<List<string>>("data/skills.json");
tools = await http.GetFromJsonAsync<List<string>>("data/tools.json");
courses = await http.GetFromJsonAsync<List<string>>("data/courses.json");
experiences = await http.GetFromJsonAsync<List<WorkExperience>>("data/workexperiences.json");
projects = await http.GetFromJsonAsync<List<ProjectEntry>>("data/projects.json");
}
private void ToggleExperience()
{
if (!isExperience)
{
isExperience = true;
isProjects = false;
StateHasChanged();
}
}
private void ToggleProjects()
{
if (!isProjects)
{
isProjects = true;
isExperience = false;
StateHasChanged();
}
}
private string FormatDescription(string desc)
{
// Simple replacement for [text](url) markdown-style links
return System.Text.RegularExpressions.Regex.Replace(desc, @"\[(.+?)\]\((.+?)\)", "<a href=\"$2\">$1</a>");
}
}
}

View File

@ -1,6 +0,0 @@
.mobile-profile {
width: 10em;
height: 10em;
object-fit: cover;
border-radius: 0.5rem;
}

View File

@ -1,23 +0,0 @@
@page "/pokemon-sleep/admincontrol"
<div class="w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonNavMenu />
<hr class="mt-5" />
<!-- Add Pokemon (Wrap in Auth) -->
<button class="btn btn-warning mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemon-sleep/addmincontrol/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">
<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>
</NavLink>
</button>
</div>

View File

@ -1,16 +1,14 @@
@page "/pokemon-sleep/add-new-pokemon" @page "/pokemonsleep/add-new-pokemon"
@inject IPokemonService PokemonService @inject IPokemonService PokemonService
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject IJSRuntime JS
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<PageTitle>Add New Pokémon</PageTitle> <PageTitle>Add New Pokémon</PageTitle>
<PokemonNavMenu /> <PokemonHeader />
@if (isSubmitting) @if (isSubmitting)
@ -19,75 +17,113 @@
} }
else else
{ {
<div class="container"> <div class="w-50 mt-5 m-auto create-container bg-info">
<div class="card-header bg-secondary bg-gradient ml-0 py-3">
<div class="row">
<div class="col-12 text-center">
<h2 class="text-info">Add New Pokémon</h2>
</div>
</div>
</div>
<div class="container m-lg-1" >
<EditForm class=" col mb-3" Model="NewPokemon" OnValidSubmit="HandleSubmit">
<DataAnnotationsValidator />
<!-- Section 1 -->
<div class="row mt-3"> <div class="row mt-3">
<div class="d-flex justify-content-evenly p-0"> <div class="col-sm-3 input-group mb-3 ">
<!-- Pokemon #-->
<div class="mx-1 align-content-center"> <span for="PokemonId" class="input-group-text">#</span>
<div class="addcard"> <InputNumber min="0" placeholder="Pokedex #" id="PokemonId" @bind-Value="NewPokemon.PokemonId" class="form-control " required />
<PokemonForm <!-- Pokemon Name-->
formUse="ADD" <InputText placeholder="Pokemon Name" id="PokemonName" @bind-Value="NewPokemon.PokemonName" class="form-control w-75" required />
OnPokemonReady="ReceivePokemon1"
mostRecentForm=false
/>
</div> </div>
</div> </div>
<!-- Pokemon Type, Sleep Type, and Speciality -->
<div class="row">
<!-- Pokemon Type -->
<div class="col mb-3 m-auto">
<label for="PokemonType" class="form-label">Pokemon Type</label>
<InputSelect id="PokemonType" @bind-Value="NewPokemon.PokemonType" class="form-select">
<option dsabled value="">Select Type</option>
<option value="Grass">Grass</option>
<option value="Fire">Fire</option>
<option value="Water">Water</option>
<option value="Normal">Normal</option>
<option value="Flying">Flying</option>
<option value="Bug">Bug</option>
<option value="Poison">Poison</option>
<option value="Electric">Electric</option>
<option value="Ground">Ground</option>
<option value="Rock">Rock</option>
<option value="Ice">Ice</option>
<option value="Steel">Steel</option>
<option value="Fighting">Fighting</option>
<option value="Psychic">Psychic</option>
<option value="Dark">Dark</option>
<option value="Fairy">Fairy</option>
<option value="Ghost">Ghost</option>
<option value="Dragon">Dragon</option>
</InputSelect>
</div>
<!-- Sleep Type -->
<div class="col mb-3 m-auto">
<label for="SleepType" class="form-label">Sleep Type</label>
<InputSelect id="SleepType" @bind-Value="NewPokemon.SleepType" class="form-select">
<option value="Dozing">Dozing</option>
<option value="Snoozing">Snoozing</option>
<option value="Slumbering">Slumbering</option>
</InputSelect>
</div>
<!-- Speciality-->
<div class="col mb-3 m-auto">
<label for="Speciality" class="form-label">Specialty</label>
<InputSelect id="Speciality" @bind-Value="NewPokemon.Speciality" class="form-select">
<option value="Berries">Berries</option>
<option value="Ingredients">Ingredients</option>
<option value="Skills">Skills</option>
<option value="All">All</option>
</InputSelect>
</div>
</div>
@if(!pokemon2FormView && !pokemon3FormView) <!-- Section 2 -->
{ <div class="row">
<div class="mx-1 align-content-center"> <div class="input-group mb-3">
<PokemonAddButton OnAdd="TogglePokemon2FormView" /> <!-- Variation Check -->
<div class=" d-inline-flex">
<InputCheckbox id="IsVariation" @bind-Value="NewPokemon.IsVariation" @onclick="@Toggle" class="form-check-input checkbox-styling p-3 mt-1" />
<span for="IsVariation" class="input-group-text m-1">Variation?</span>
</div> </div>
}
<!-- Variation Region Input -->
<div class="w-75 mx-2 mt-1">
else if (pokemon2FormView && !pokemon3FormView) <InputText placeholder="What Variant? (Alolan, Paldean)" hidden="@HideLabel" id="VariationName" @bind-Value="NewPokemon.VariationName" class="form-control" />
{
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonForm OnPokemonReady="ReceivePokemon2"
formUse="ADD"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
</div> </div>
</div> </div>
<div class="mx-1 align-content-center">
<PokemonAddButton OnAdd="TogglePokemon3FormView" />
</div> </div>
} <!-- New Image URL Field -->
<div class="row mb-3 m-auto">
<label for="ImageUrl" class="form-label">Base Image URL</label>
<InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonImageUrl" class="form-control" />
</div>
<div class="row mb-3 m-auto">
<label for="ImageUrl" class="form-label">Shiny Image URL</label>
<InputText id="ImageUrl" @bind-Value="NewPokemon.PokemonShinyImageUrl" class="form-control" />
</div>
<!-- Form Buttons -->
else if (!pokemon2FormView && pokemon3FormView) <div class="d-flex justify-content-between">
{ <button type="button" class="btn btn-secondary mb-3" @onclick="Cancel">Cancel</button>
<div class="mx-1 align-content-center"> <button type="submit" class="btn btn-primary mb-3">Add Pokemon</button>
<div class="addcard">
<PokemonForm OnPokemonReady="ReceivePokemon2"
formUse="ADD"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
</div> </div>
</div> </EditForm>
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonForm OnPokemonReady="ReceivePokemon3"
formUse="ADD"
RemoveForm="TogglePokemon3FormView"
mostRecentForm="@pokemon3FormView" />
</div> </div>
</div> </div>
} }
</div>
</div>
</div>
<div class="d-flex justify-content-center mt-5">
<div class="btn-group">
<button @onclick="@HandleAdd" class="btn btn-primary rounded">Add Pokemon</button>
</div>
</div>
}

View File

@ -1,59 +1,24 @@
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using Portfolio.Domain.Features.Pokemon; using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{ {
public partial class PokemonCreate public partial class PokemonCreate
{ {
private bool pokemon2FormView { get; set; } = false;
private bool pokemon3FormView { get; set; } = false;
private bool HideLabel { get; set; } = true; private bool HideLabel { get; set; } = true;
private void Toggle() private void Toggle()
{ {
HideLabel = !HideLabel; HideLabel = !HideLabel;
} }
private void TogglePokemon2FormView()
{
pokemon2FormView = !pokemon2FormView;
}
private void TogglePokemon3FormView()
{
pokemon3FormView = !pokemon3FormView;
TogglePokemon2FormView();
} private Pokemon NewPokemon = new Pokemon
// Create up to 3 Pokemon
private Pokemon pokemon1 = new Pokemon
{ {
PokemonId = 0, // Or any default ID logic PokemonId = 0, // Or any default ID logic
PokemonName = string.Empty, // Required fields cannot be null PokemonName = string.Empty, // Required fields cannot be null
PokemonType = string.Empty,
SleepType = string.Empty, SleepType = string.Empty,
Speciality = string.Empty, Speciality = string.Empty,
IsVariation = false IsVariation = false
}; };
private Pokemon pokemon2 = new Pokemon
{
PokemonId = 0, // Or any default ID logic
PokemonName = string.Empty, // Required fields cannot be null
PokemonType = string.Empty,
SleepType = string.Empty,
Speciality = string.Empty,
IsVariation = false
};
private Pokemon pokemon3 = new Pokemon
{
PokemonId = 0, // Or any default ID logic
PokemonName = string.Empty, // Required fields cannot be null
PokemonType = string.Empty,
SleepType = string.Empty,
Speciality = string.Empty,
IsVariation = false
};
private bool isSubmitting = false; private bool isSubmitting = false;
private bool ToggleVariationName { get; set; } private bool ToggleVariationName { get; set; }
@ -62,104 +27,19 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{ {
this.ToggleVariationName = true; this.ToggleVariationName = true;
} }
private async Task HandleSubmit()
private async Task ReceivePokemon1(Pokemon p)
{
// Save received pokemon as Pokemon 1
pokemon1 = p;
// Server console (Blazor Server)
Console.WriteLine($"[Pokemon 1] #{pokemon1.PokemonId} {pokemon1.PokemonName} | {pokemon1.PokemonType} | {pokemon1.SleepType} | {pokemon1.Speciality} | Var:{pokemon1.IsVariation} {pokemon1.VariationName}");
// Browser console
await JS.InvokeVoidAsync("console.log", "Pokemon 1:", pokemon1);
}
private async Task ReceivePokemon2(Pokemon p)
{
// Save received pokemon as Pokemon 1
pokemon2 = p;
// Server console (Blazor Server)
Console.WriteLine($"[Pokemon 2] #{pokemon2.PokemonId} {pokemon2.PokemonName} | {pokemon2.PokemonType} | {pokemon2.SleepType} | {pokemon2.Speciality} | Var:{pokemon2.IsVariation} {pokemon2.VariationName}");
// Browser console
await JS.InvokeVoidAsync("console.log", "Pokemon 2:", pokemon2);
}
private async Task ReceivePokemon3(Pokemon p)
{
// Save received pokemon as Pokemon 1
pokemon3 = p;
// Server console (Blazor Server)
Console.WriteLine($"[Pokemon 3] #{pokemon3.PokemonId} {pokemon3.PokemonName} | {pokemon3.PokemonType} | {pokemon3.SleepType} | {pokemon3.Speciality} | Var:{pokemon3.IsVariation} {pokemon3.VariationName}");
// Browser console
await JS.InvokeVoidAsync("console.log", "Pokemon 3:", pokemon3);
}
private bool IsComplete(Pokemon NewPokemon) =>
NewPokemon.PokemonId > 0 &&
!string.IsNullOrWhiteSpace(NewPokemon.PokemonName) &&
!string.IsNullOrWhiteSpace(NewPokemon.PokemonType) &&
!string.IsNullOrWhiteSpace(NewPokemon.SleepType) &&
!string.IsNullOrWhiteSpace(NewPokemon.Speciality) &&
(!NewPokemon.IsVariation || !string.IsNullOrWhiteSpace(NewPokemon.VariationName));
private async Task HandleAdd()
{
/*
Okay there are three versions of submits which need to be checked
1. Single submit, only one, if both pokemon#FormView is false
2. 2 Submit, if pokemon2FormView is true
3. 3 Submit, if pokemon3FormView is true
*/
if (!pokemon2FormView && !pokemon3FormView)
{
//if(IsComplete(pokemon1))
//{
await HandleSubmit(pokemon1);
Navigation.NavigateTo("/pokemon-sleep/pokemon");
//}
}
else if (pokemon2FormView)
{
//if (IsComplete(pokemon1) && IsComplete(pokemon2))
//{
await HandleSubmit(pokemon1);
await HandleSubmit(pokemon2);
Navigation.NavigateTo("/pokemon-sleep/pokemon");
// }
}
else if (pokemon3FormView)
{
//if (IsComplete(pokemon1) && IsComplete(pokemon2) && IsComplete(pokemon3))
//{
await HandleSubmit(pokemon1);
await HandleSubmit(pokemon2);
await HandleSubmit(pokemon3);
Navigation.NavigateTo("/pokemon-sleep/pokemon");
//}
}
}
private async Task HandleSubmit(Pokemon NewPokemon)
{ {
isSubmitting = true; isSubmitting = true;
await PokemonService.AddPokemonAsync(NewPokemon); await PokemonService.AddPokemonAsync(NewPokemon);
isSubmitting = false; isSubmitting = false;
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-sleep/pokemon"); Navigation.NavigateTo("/pokemonsleep");
} }
} }
} }

View File

@ -1,5 +1,9 @@
.addcard { 
width: 100%; .create-container {
max-width: 25rem; 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;
} }
.checkbox-styling {
border: 1px solid black;
}

View File

@ -1,41 +1,132 @@
@page "/pokemon-sleep/edit-pokemon/{id:int}" @page "/pokemonsleep/edit/{id:int}"
@inject IPokemonService PokemonService @inject IPokemonService PokemonService
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject IJSRuntime JS @inject IJSRuntime JSRuntime
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<PageTitle>Edit Pokémon</PageTitle> <PageTitle>Edit Pokémon</PageTitle>
<PokemonNavMenu /> <PokemonHeader />
@if (pokemon == null) @if (pokemon == null)
{ {
<Loading /> <p><em>Loading...</em></p>
} }
else else
{ {
<!-- Total Componenet-->
<div class="w-50 mt-3 m-auto bg-info edit-container">
<div class="container mt-5 w-50 mb-5"> <!-- Header -->
<div class="row d-flex flex-row mb-0 justify-content-center"> <div class="card-header bg-secondary ml-0 py-3 w-100 ">
<div class="w-50"> <div class="row">
<div class="editcard"> <div class="col-12 text-center">
<PokemonForm <h2 class="text-info">Edit Pokémon</h2>
formUse="EDIT"
OnPokemonReady="ReceivePokemon"
RemoveForm="Cancel"
mostRecentForm=true
PokemonToEdit="pokemon"
/>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="d-flex justify-content-center">
<div class="btn-group">
<button @onclick="@HandleSubmit" class="btn btn-primary rounded">Edit Pokemon</button>
</div>
</div>
<!-- Body -->
<div class="p-3 w-100 flex-column ">
<EditForm class="col mb-3" Model="pokemon" OnValidSubmit="HandleSubmit">
<DataAnnotationsValidator />
<!-- Dex Number and Name -->
<div class="row ">
<div class="col-sm-3 input-group mb-3">
<span for="PokemonId" class="input-group-text">#</span>
<InputNumber min="0" id="PokemonId" @bind-Value="pokemon.PokemonId" class="form-control" required disabled />
<InputText id="PokemonName" @bind-Value="pokemon.PokemonName" class="form-control w-75" required />
</div>
</div>
<!-- Pokemon Type, Sleep Type, and Speciality -->
<div class="row">
<!-- Pokemon Type -->
<div class="col mb-3 m-auto">
<label for="PokemonType" class="form-label">Pokemon Type</label>
<InputSelect id="PokemonType" @bind-Value="pokemon.PokemonType" class="form-select">
<option dsabled value="">Select Type</option>
<option value="Grass">Grass</option>
<option value="Fire">Fire</option>
<option value="Water">Water</option>
<option value="Normal">Normal</option>
<option value="Flying">Flying</option>
<option value="Bug">Bug</option>
<option value="Poison">Poison</option>
<option value="Electric">Electric</option>
<option value="Ground">Ground</option>
<option value="Rock">Rock</option>
<option value="Ice">Ice</option>
<option value="Steel">Steel</option>
<option value="Fighting">Fighting</option>
<option value="Psychic">Psychic</option>
<option value="Dark">Dark</option>
<option value="Fairy">Fairy</option>
<option value="Ghost">Ghost</option>
<option value="Dragon">Dragon</option>
</InputSelect>
</div>
<!-- Sleep Type -->
<div class="col mb-3 m-auto">
<label for="SleepType" class="form-label">Sleep Type</label>
<InputSelect id="SleepType" @bind-Value="pokemon.SleepType" class="form-select">
<option value="Dozing">Dozing</option>
<option value="Snoozing">Snoozing</option>
<option value="Slumbering">Slumbering</option>
</InputSelect>
</div>
<!-- Speciality-->
<div class="col mb-3 m-auto">
<label for="Speciality" class="form-label">Specialty</label>
<InputSelect id="Speciality" @bind-Value="pokemon.Speciality" class="form-select">
<option value="Berries">Berries</option>
<option value="Ingredients">Ingredients</option>
<option value="Skills">Skills</option>
</InputSelect>
</div>
</div>
<!-- Variation Check -->
<div class="row">
<div class="input-group mb-3">
<!-- Variation Check -->
<div class=" d-inline-flex">
<InputCheckbox id="IsVariation" @bind-Value="pokemon.IsVariation" @onclick="@Toggle" class="form-check-input checkbox-styling p-3 mt-1" />
<span for="IsVariation" class="input-group-text m-1">Variation?</span>
</div>
<!-- Variation Region Input -->
<div class="w-75 mx-2 mt-1">
<InputText placeholder="What Variant? (Alolan, Paldean)" hidden="@HideLabel" id="VariationName" @bind-Value="pokemon.VariationName" class="form-control" />
</div>
</div>
</div>
<!-- Image URL Input -->
<div class="row mb-3 m-auto">
<label for="ImageUrl" class="form-label">Base Image URL</label>
<InputText id="ImageUrl" @bind-Value="pokemon.PokemonImageUrl" class="form-control" />
</div>
<!-- Shiny Image URL Input -->
<div class="row mb-3 m-auto">
<label for="ImageUrl" class="form-label">Shiny Image URL</label>
<InputText id="ImageUrl" @bind-Value="pokemon.PokemonShinyImageUrl" class="form-control" />
</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="pokemon.FlavorText" class="form-control" />
</div>
<!-- Form Buttons -->
<div class="d-flex justify-content-between">
<button type="button" class="btn btn-secondary mb-3" @onclick="Cancel">Cancel</button>
<button type="submit" class="btn btn-primary mb-3">Save Changes</button>
</div>
</EditForm>
</div>
</div>
} }

View File

@ -14,28 +14,16 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
pokemon = await PokemonService.GetPokemonByIdAsync(Id); pokemon = await PokemonService.GetPokemonByIdAsync(Id);
} }
private async Task ReceivePokemon(Pokemon p)
{
// Save received pokemon as Pokemon 1
pokemon = p;
// Server console (Blazor Server)
Console.WriteLine($"[Pokemon 1] #{pokemon.PokemonId} {pokemon.PokemonName} | {pokemon.PokemonType} | {pokemon.SleepType} | {pokemon.Speciality} | Var:{pokemon.IsVariation} {pokemon.VariationName}");
// Browser console
await JS.InvokeVoidAsync("console.log", "Pokemon 1:", pokemon);
}
private async Task HandleSubmit() private async Task HandleSubmit()
{ {
await PokemonService.UpdatePokemonAsync(pokemon); await PokemonService.UpdatePokemonAsync(pokemon);
//Navigation.NavigateTo("/pokemonsleep"); //Navigation.NavigateTo("/pokemonsleep");
await JS.InvokeVoidAsync("history.back"); await JSRuntime.InvokeVoidAsync("history.back");
} }
private async void Cancel() private async void Cancel()
{ {
await JS.InvokeVoidAsync("history.back"); await JSRuntime.InvokeVoidAsync("history.back");
} }

View File

@ -5,8 +5,3 @@
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(255,255, 255, 0.19); 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; border-radius: 15px;
} }
.editcard {
width: 100%;
max-width: 30rem;
}

View File

@ -1,93 +0,0 @@
@page "/pokemon-sleep/pokemon/{id:int}"
@inject IPokemonService PokemonService
@inject NavigationManager Navigation
@attribute [StreamRendering]
@rendermode InteractiveServer
<PokemonNavMenu />
@if (_pokemon == null)
{
<Loading />
}
else
{
<PageTitle>@_pokemon.PokemonName</PageTitle>
<!-- Total Componenet-->
<div class="container">
<div class="w-75 lg row mt-5 m-auto">
<!-- 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">
<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" />
</svg>
</button>
</div>
<!-- Pokemon Presentation -->
<div class="mt-5 mx-5 col justify-content-center">
@if (_variationPokemonId != null)
{
@if (_variationPokemonId != null && _pokemonVariant == null){
<Loading />
}
else
{
<!-- If Variation Pokemon have same PokemonId -->
@if(_pokemon.Id != _pokemonVariant.Id)
{
<div class="d-flex justify-content-center">
<div class="pokemoncard m-1">
<PokemonCard Pokemon="_pokemon" />
</div>
<div class="pokemoncard m-1">
<PokemonCard Pokemon="_pokemonVariant" />
</div>
</div>
}
<!-- If Variation Pokemon has diff PokemonId -->
else
{
<div class="d-flex justify-content-center align-items-center h-100">
<div class="pokemoncard">
<PokemonCard Pokemon="_pokemonVariant" />
</div>
</div>
}
}
}
else{
<!-- Standard Pokemon Display -->
<div class="d-flex justify-content-center align-items-center h-100">
<div class="pokemoncard m-1">
<PokemonCard Pokemon="_pokemon" />
</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">
<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" />
</svg>
</button>
</div>
</div>
</div>
}

View File

@ -1,52 +0,0 @@
using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{
public partial class PokemonIndividualView
{
[Parameter] public int Id { get; set; }
private Pokemon? _pokemon;
private Pokemon? _pokemonVariant;
private List<int> _pokemonIds;
private int? _nextPokemonId;
private int? _previousPokemonId;
private int? _variationPokemonId;
private int _currentIndex;
protected override async Task OnParametersSetAsync()
{
_pokemon = await PokemonService.GetPokemonByPokemonIdAsync(Id);
// These can be smart queries if your data is sorted by ID or by another property
_pokemonIds = await PokemonService.GetAllPokemonIdsAsync();
_currentIndex = _pokemonIds.IndexOf(_pokemon.PokemonId);
//Console.WriteLine(_currentIndex);
_nextPokemonId = await PokemonService.GetNextPokemonIdAsync(Id);
_previousPokemonId = await PokemonService.GetPreviousPokemonIdAsync(Id);
_variationPokemonId = await PokemonService.GetVariationPokemonIdAsync(Id);
if (_variationPokemonId != null)
{
Console.WriteLine(_variationPokemonId);
_pokemonVariant = await PokemonService.GetPokemonByIdAsync((int)_variationPokemonId);
Console.WriteLine(_pokemonVariant.VariationName);
}
}
private void NavigateToNext()
{
if (_nextPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{_nextPokemonId.Value}");
}
private void NavigateToPrevious()
{
if (_previousPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{_previousPokemonId.Value}");
}
}
}

View File

@ -1,9 +0,0 @@
.pokemoncard {
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

@ -1,63 +1,185 @@
@page "/pokemon-sleep/rate-pokemon" @page "/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
<PageTitle>Rate Pokémon</PageTitle> <PageTitle>Rate Pokémon</PageTitle>
<PokemonNavMenu /> <PokemonHeader />
<div class="container 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>
</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

@ -1,185 +1,19 @@
@page "/pokemon-sleep" @page "/pokemon"
@inject IPokemonService PokemonService
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<PageTitle>Pokémon Sleep</PageTitle> <PageTitle>Pokémon Sleep</PageTitle>
<div class="w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> --> <!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonNavMenu />
<!-- Large --> <PokemonHeader />
<div class="container d-none d-lg-block d-md-none card shadow-sm border-0 p-3 pb-4 mt-5 w-50 mb-5 bg-white rounded ">
<!-- Top Row--> <PokemonTable AllPokemon="pokemons"/>
<div class="row d-flex flex-row px-3 mb-0 pb-0">
<!-- Image side -->
<div class="col-4 p-0">
<img class="shadow-sm m-auto img-fluid rounded" src="images/Pokemon_Sleep_ID.jpg" />
</div>
<!-- Text side -->
<div class="col w-50 p-3 ps-4 pb-0">
<div class="row">
<p class="fw-bold fst-italic fs-3 mb-0">Pokémon Sleep? Really?</p>
<p class="fw-normal fs-6 font-monospace">
Yes, really! Pokémon Sleep has become a fun addition to my day since it's release. Scan the QR code in the Pokémon Sleep app to send me a friend request!
</p>
</div>
<div class="row">
<p class="fw-bold fst-italic fs-3 mb-0">But what do you even do?</p>
<p class="fw-normal fs-6 font-monospace">
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>
</div>
</div>
</div>
<!-- Second Row -->
<div class="row mt-0 pt-0">
<p class="fw-bold fst-italic fs-3 mb-0">Okay, but why a whole section dedicated to Pokémon Sleep?</p>
<p class="fw-normal fs-6 font-monospace">
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>
</div>
<!-- Button Row-->
<div class="row d-flex justify-content-evenly mt-3 ">
<button class="btn btn-info rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/pokemon">
<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" />
</svg>
<span class="ps-1 text-white">Available Pokémon</span>
</NavLink>
</button>
<button class="btn btn-success rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" 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="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" />
</svg>
<span class="ps-1 text-white">Rate Pokémon</span>
</NavLink>
</button>
</div>
</div>
<!-- Medium -->
<div class="container d-none d-lg-none d-md-block mt-3">
<!-- Top Row-->
<div class="row d-flex flex-row justify-content-center">
<!-- Top side -->
<div class="col p-0" >
<img class="shadow-sm m-auto img-fluid rounded" src="images/Pokemon_Sleep_ID.jpg" />
</div>
<div class="col text-wrap p-1 ps-3" >
<div class="row d-flex flex-row justify-content-center">
<!-- Bottom side -->
<p class="fw-bold fst-italic fs-3 mb-1">Pokémon Sleep? Really?</p>
<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. Scan the QR code in the Pokémon Sleep app to send me a friend request!
</p>
</div>
<p class="fw-bold fst-italic fs-3 mb-0">But what do you even do?</p>
<div class="row d-flex flex-row justify-content-center">
<!-- Bottom side -->
<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.
</p>
</div>
</div>
</div>
<!-- Second Row -->
<div class="row d-flex flex-row justify-content-center p-1">
<p class="fw-bold fst-italic fs-3 mb-0">Okay, but why a whole section dedicated to Pokémon Sleep?</p>
<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.
</p>
</div>
<!-- Button Row-->
<div class="row d-flex justify-content-evenly mt-3 ">
<button class="btn btn-info rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/pokemon">
<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" />
</svg>
<span class="ps-1 text-white">Available Pokémon</span>
</NavLink>
</button>
<button class="btn btn-success rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" 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="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" />
</svg>
<span class="ps-1 text-white">Rate Pokémon</span>
</NavLink>
</button>
</div>
</div>
<!-- Small -->
<div class="container d-inline d-lg-none d-md-none mt-3 mx-auto">
<!-- Image-->
<div class="row d-flex flex-row justify-content-center">
<!-- Top side -->
<div class="col-6">
<img class="img-fluid rounded p-0" src="images/Pokemon_Sleep_ID.jpg" />
</div>
</div>
<div class="row mt-2 w-75 mx-auto p-1 ps-3">
<p class="fw-bold fst-italic fs-4 mb-1">Pokémon Sleep? Really?</p>
<p class="fw-normal fs-6 font-monospace">
Yes, really! Pokémon Sleep has become a fun addition to my day since it's release. Scan the QR code in the Pokémon Sleep app to send me a friend request!
</p>
<p class="fw-bold fst-italic fs-4 mb-0">But what do you even do?</p>
<p class="fw-normal fs-6 font-monospace">
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 class="fw-bold fst-italic fs-4 mb-0">Okay, but why a whole section dedicated to Pokémon Sleep?</p>
<p class="fw-normal fs-6 font-monospace">
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>
</div>
<!-- Button Row-->
<div class="row d-flex justify-content-evenly mt-2">
<button class="btn btn-info rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/pokemon">
<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" />
</svg>
<span class="ps-1 text-white">Available Pokémon</span>
</NavLink>
</button>
<button class="btn btn-success rounded-4 d-flex justify-content-center" style="width:12rem;">
<NavLink class="nav-link d-flex align-items-center" href="/pokemon-sleep/rate-pokemon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFF" 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="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1z" />
</svg>
<span class="ps-1 text-white">Rate Pokémon</span>
</NavLink>
</button>
</div>
</div> </div>

View File

@ -0,0 +1,30 @@
using Portfolio.Application.Services.PokemonService;
using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{
public partial class PokemonSleep
{
public List<Pokemon> pokemons = new List<Pokemon>();
public List<string> pokemonImageUrls = new List<string>();
public List<string> pokemonShinyImageUrls = new List<string>();
protected override async Task OnInitializedAsync()
{
var result = await PokemonService.GetAllPokemonAsync();
if (result is not null)
{
pokemons = result;
pokemons.Sort((x, y) => x.PokemonId.CompareTo(y.PokemonId));
foreach (var pokemon in pokemons)
{
pokemonImageUrls.Add(pokemon.PokemonImageUrl);
pokemonShinyImageUrls.Add(pokemon.PokemonShinyImageUrl);
}
}
}
}
}

View File

@ -0,0 +1,93 @@

.tableFixHead {
overflow: auto;
height: 600px;
}
.tableFixHead thead th {
position: sticky;
top: 0;
z-index: 10;
}
.flip-container {
perspective: 1000px;
display: inline-block;
width: 90px;
height: 90px;
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: 100px;
height: 30px;
color: white;
padding: 4px 8px;
text-align: center;
vertical-align: middle;
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;
}
.page-content {
position: relative;
z-index: 1; /* Higher than stickers */
background-color: rgba(255, 255, 255, 0.8); /* Optional translucent bg */
}

View File

@ -0,0 +1,73 @@
@page "/pokemonsleep"
@attribute [StreamRendering]
@rendermode InteractiveServer
<PageTitle>Pokémon Sleep</PageTitle>
<div class="container">
<div class="row w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<div class="row"><PokemonHeader /></div>
<!-- Card -->
<div class="row card shadow-sm border-0 p-3 pb-4 mt-4 m-auto w-75">
<!-- Top Row-->
<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-normal fs-6 text-start">
Yes, really! Pokémon Sleep has become a fun addition to my day since it's release.
</p>
<p class="fw-bold fst-italic fs-3">But what do you even do?</p>
<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.
</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-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.
</p>
</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 class="w-auto">
<button class="btn btn-success link">
<NavLink href="/rate-pokemon">
<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">
<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>

View File

@ -1,22 +1,81 @@
@page "/pokemon-sleep/pokemon" @page "/pokemon/{id:int}"
@inject IPokemonService PokemonService @inject IPokemonService PokemonService
@inject NavigationManager Navigation
@attribute [StreamRendering] @attribute [StreamRendering]
@rendermode InteractiveServer @rendermode InteractiveServer
<PageTitle>Pokémon Sleep</PageTitle> <PokemonHeader />
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonNavMenu />
<PokemonTable AllPokemon="pokemons"/>
@if (_pokemon == null)
{
<Loading />
}
else
{
<PageTitle>@_pokemon.PokemonName</PageTitle>
<!-- Total Componenet-->
<div class="w-100">
<div class="d-flex justify-content-center mt-4">
<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">
<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>
</button>
<div class="mt-5 mx-5 d-flex justify-content-center">
@if (_variationPokemonId != null)
{
@if (_variationPokemonId != null && _pokemonVariant == null){
<Loading />
}
else
{
@if(_pokemon.Id != _pokemonVariant.Id)
{
<div class="d-flex justify-content-center">
<div class="position-relative">
<PokemonCard Pokemon="_pokemon" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemon.Id" />
</div>
</div>
<div class="position-relative">
<PokemonCard Pokemon="_pokemonVariant" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemonVariant.Id" />
</div>
</div>
</div>
}
else
{
<div class="position-relative">
<PokemonCard Pokemon="_pokemonVariant" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemonVariant.Id" />
</div>
</div>
}
}
}
else{
<div class="position-relative">
<PokemonCard Pokemon="_pokemon" />
<div class="position-absolute top-100 start-50 translate-middle mt-5">
<PokemonEditButton PokemonId="_pokemon.Id" />
</div>
</div>
}
</div>
<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">
<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" />
</svg>
</button>
</div>
</div>
}

View File

@ -1,30 +1,52 @@
using Portfolio.Application.Services.PokemonService; using Microsoft.AspNetCore.Components;
using Portfolio.Domain.Features.Pokemon; using Portfolio.Domain.Features.Pokemon;
namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{ {
public partial class PokemonView public partial class PokemonView
{ {
public List<Pokemon> pokemons = new List<Pokemon>(); [Parameter] public int Id { get; set; }
public List<string> pokemonImageUrls = new List<string>(); private Pokemon? _pokemon;
public List<string> pokemonShinyImageUrls = new List<string>(); private Pokemon? _pokemonVariant;
private List<int> _pokemonIds;
private int? _nextPokemonId;
private int? _previousPokemonId;
private int? _variationPokemonId;
private int _currentIndex;
protected override async Task OnInitializedAsync() protected override async Task OnParametersSetAsync()
{ {
var result = await PokemonService.GetAllPokemonAsync(); _pokemon = await PokemonService.GetPokemonByPokemonIdAsync(Id);
if (result is not null)
{
pokemons = result;
pokemons.Sort((x, y) => x.PokemonId.CompareTo(y.PokemonId));
foreach (var pokemon in pokemons) // These can be smart queries if your data is sorted by ID or by another property
_pokemonIds = await PokemonService.GetAllPokemonIdsAsync();
_currentIndex = _pokemonIds.IndexOf(_pokemon.PokemonId);
//Console.WriteLine(_currentIndex);
_nextPokemonId = await PokemonService.GetNextPokemonIdAsync(Id);
_previousPokemonId = await PokemonService.GetPreviousPokemonIdAsync(Id);
_variationPokemonId = await PokemonService.GetVariationPokemonIdAsync(Id);
if (_variationPokemonId != null)
{ {
pokemonImageUrls.Add(pokemon.PokemonImageUrl); Console.WriteLine(_variationPokemonId);
pokemonShinyImageUrls.Add(pokemon.PokemonShinyImageUrl); _pokemonVariant = await PokemonService.GetPokemonByIdAsync((int)_variationPokemonId);
Console.WriteLine(_pokemonVariant.VariationName);
}
}
private void NavigateToNext()
{
if (_nextPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon/{_nextPokemonId.Value}");
}
private void NavigateToPrevious()
{
if (_previousPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon/{_previousPokemonId.Value}");
} }
} }
} }
}
}

View File

@ -1,93 +1,2 @@
 body {
.tableFixHead {
overflow: auto;
height: 600px;
} }
.tableFixHead thead th {
position: sticky;
top: 0;
z-index: 10;
}
.flip-container {
perspective: 1000px;
display: inline-block;
width: 90px;
height: 90px;
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: 100px;
height: 30px;
color: white;
padding: 4px 8px;
text-align: center;
vertical-align: middle;
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;
}
.page-content {
position: relative;
z-index: 1; /* Higher than stickers */
background-color: rgba(255, 255, 255, 0.8); /* Optional translucent bg */
}

View File

@ -12,7 +12,6 @@
@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.WebUI.Server.Components.Component.Crochet_Components
@using Portfolio.Domain.Features.Articles @using Portfolio.Domain.Features.Articles
@using Portfolio.Domain.Features.Portfolio;
@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

View File

@ -8,11 +8,6 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents() builder.Services.AddRazorComponents()
.AddInteractiveServerComponents(); .AddInteractiveServerComponents();
builder.Services.AddHttpClient("LocalClient", client =>
{
client.BaseAddress = new Uri("https://localhost:7189/"); // or whatever your port is
});
builder.Services.AddApplication(); builder.Services.AddApplication();
builder.Services.AddInfrastructure(builder.Configuration); builder.Services.AddInfrastructure(builder.Configuration);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
[
"Adv. Web Development",
"Operating Systems",
"Game Development",
"Parallel Programming",
"VR / AR Development",
"Artificial Intelligence",
"Machine Learning",
"Computer Graphics",
"Data Visualization",
"Database Management",
"Analysis of Algorithms"
]

View File

@ -1,98 +0,0 @@
[
{
"name": "Large Leek",
"description": "Whether this is the kind of vegetable stalk that Farfetch'd like is unknown.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/largeleek.png"
},
{
"name": "Tasty Mushroom",
"description": "A juicy mushroom with an abundance of umami flavor.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/tastymushroom.png"
},
{
"name": "Fancy Egg",
"description": "A nutritious cooking name that goes well with all sorts of seasonings.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/fancyegg.png"
},
{
"name": "Soft Potato",
"description": "Its mellow flavor makes both body and spirit feel warm and fuzzy.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/softpotato.png"
},
{
"name": "Fancy Apple",
"description": "An apple chosen above others. It has spectacular form and a brilliant sheen.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/fancyapple.png"
},
{
"name": "Fiery Herb",
"description": "The fiery taste of this bright-red herb will wake anyone right up.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/fieryherb.png"
},
{
"name": "Bean Sausage",
"description": "A healthy sausage made from beans that Pok<6F>mon like to eat.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/beansausage.png"
},
{
"name": "Moomoo Milk",
"description": "Highly nutritious milk. Pok<6F>mon that drink it become full of energy.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/moomoomilk.png"
},
{
"name": "Honey",
"description": "A sweet honey collected by Pok<6F>mon.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/honey.png"
},
{
"name": "Pure Oil",
"description": "All-purpose oil that can be used in any type of cuisine.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/pureoil.png"
},
{
"name": "Warming Ginger",
"description": "Spicy ginger that warms the body better than any other name.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/warmingginger.png"
},
{
"name": "Snoozy Tomato",
"description": "A bright-red tomato. Eat it and you'll sleep like a baby.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/snoozytomato.png"
},
{
"name": "Soothing Cacao",
"description": "This cacao bean is time-consuming to process, but its soothing effects make the effort worthwhile.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/soothingcacao.png"
},
{
"name": "Slowpoke Tail",
"description": "A very tasty tail of something. When it falls off, it grows back quickly.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/slowpoketail.png"
},
{
"name": "Greengrass Soybeans",
"description": "This Greengrass Isle specialty is easy to process into foods that are great for training.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/greengrasssoybeans.png"
},
{
"name": "Greengrass Corn",
"description": "This Greengrass Isle specialty can be eaten raw. It's remarkably sweet.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/greengrasscorn.png"
},
{
"name": "Rousing Coffee",
"description": "You may have trouble sleeping if you drink too much of this. It may help make you feel more alert.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/rousingcoffee.png"
},
{
"name": "Plump Pumpkin",
"description": "A big pumpkin packed full of pulp.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/plumppumpkin.png"
},
{
"name": "Glossy Avocado",
"description": "The glossy green shine is a sign it' s freshly picked.",
"imageURL": "https://www.serebii.net/pokemonsleep/names/glossyavocado.png"
}
]

View File

@ -1,129 +0,0 @@
[
{
"type": "Grass",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/grass.png",
"berry": "Durin",
"berryDescription": "This Berry is tremendously bitter. Just one bite is enough to instantly stop hiccups.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/durinberry.png"
},
{
"type": "Fire",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/fire.png",
"berry": "Leppa",
"berryDescription": "It takes longer to grow than Berries such as Cheri. The smaller Berries taste better.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/leppaberry.png"
},
{
"type": "Water",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/water.png",
"berry": "Oran",
"berryDescription": "Nature's gifts came together as one in this Berry. It has a wondrous mix of flavors that spread in the mouth.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/oranberry.png"
},
{
"type": "Normal",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/normal.png",
"berry": "Persim",
"berryDaescription": "The more this Berry absorbs energy from sunlight, the more vividly colorful it grows.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/persimberry.png"
},
{
"type": "Flying",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/flying.png",
"berry": "Pamtre",
"berryDescription": "This Berry drifted from a faraway sea. It can now be cultivated even on this island.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/pamtreberry.png"
},
{
"type": "Bug",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/bug.png",
"berry": "Lum",
"berryDescription": "This Berry's gradual process of storing nutrients beneficial to Pok<6F>mon health causes it to mature slowly.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/lumberry.png"
},
{
"type": "Poison",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/poison.png",
"berry": "Chesto",
"berryDescription": "This Berry's thick skin and fruit are very tough and dry-tasting. However, every bit of it can be eaten.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/chestoberry.png"
},
{
"type": "Electric",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/electric.png",
"berry": "Grepa",
"berryDescription": "One bite of this very tender Berry fills the mouth with its sweet and tangy flavor.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/grepaberry.png"
},
{
"type": "Ground",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/ground.png",
"berry": "Figy",
"berryDescription": "This Berry is oddly shaped, appearing as if someone took a bite out of it. It's packed full of spicy substances.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/figyberry.png"
},
{
"type": "Rock",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/rock.png",
"berry": "Sitrus",
"berryDescription": "Sitrus came from the same family as Oran. It's larger and smoother- tasting than Oran.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/sitrusberry.png"
},
{
"type": "Ice",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/ice.png",
"berry": "Rawst",
"berryDescription": "If the leaves grow longer and curlier than average, this Berry will have a somewhat bitter taste.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/rawstberry.png"
},
{
"type": "Steel",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/steel.png",
"berry": "Belue",
"berryDescription": "This glossy and colorful Berry has a mouthwateringly delicious appearance. However, it's awfully sour.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/belueberry.png"
},
{
"type": "Fighting",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/fighting.png",
"berry": "Cheri",
"berryDescription": "This bright red Berry is very spicy and has a provocative flavor. It blooms with delicate, pretty flowers.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/cheriberry.png"
},
{
"type": "Psychic",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/psychic.png",
"berry": "Mago",
"berryDescription": "This Berry progressively curves as it grows. The curvier the Berry, the sweeter it tastes.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/magoberry.png"
},
{
"type": "Dark",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/dark.png",
"berry": "Wiki",
"berryDescription": "It's said that this Berry grew lumps to help Pok<6F>mon grip it, allowing propagation farther afield.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/wikiberry.png"
},
{
"type": "Fairy",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/fairy.png",
"berry": "Pecha",
"berryDescription": "Because of its hollow inside pocket, there isn't a lot to eat. What can be eaten is very sweet and delicious.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/pechaberry.png"
},
{
"type": "Ghost",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/ghost.png",
"berry": "Bluk",
"berryDescription": "Though this small, delicately skinned Berry is blue in color, it dyes the mouth black when eaten.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/blukberry.png"
},
{
"type": "Dragon",
"typeImageUrl": "https://www.serebii.net/pokemonsleep/pokemon/type/dragon.png",
"berry": "Yache",
"berryDescription": "This Berry has a refreshing flavor that strikes a good balance of dryness and sourness. It tastes better chilled.",
"berryImageURL": "https://www.serebii.net/pokemonsleep/berries/yacheberry.png"
}
]

View File

@ -1,87 +0,0 @@
[
{
"title": "Temperature Blanket Visualizer",
"descriptions": [
"Useful tool to help visualize and refine blanket planning for crochet temperature blankets.",
"A personal project, but a fun one."
],
"links": [
{
"type": "internal",
"url": "/temperature-blanket",
"icon": "code"
}
]
},
{
"title": "PokemonSleep Toolset",
"descriptions": [
"A webpage constructed for assisting players in the mobile game Pokemon Sleep. Featuring a Pokemon Rater that derives ratings utilizing [this public spreadsheet](https://docs.google.com/spreadsheets/d/14nzQ--k4XhpFHI0qhgNRQlpWswh6WAxBCfq_QvIVZyI/edit?gid=339317073#gid=339317073).",
"A personal project, but a fun one."
],
"links": [
{
"type": "internal",
"url": "/pokemon-sleep",
"icon": "code"
}
]
},
{
"title": "AI-Driven D&D 5E Character Generator with React, Next.js, and OpenAI GPT-3 Engine",
"descriptions": [
"Creates a credible D&D 5E character sheet, including backstory, based on user input. Ex. 'I would like to play a magical elf.' or 'I want to smash things with a big hammer.' The AI chooses the best-fitting character while ensuring rules compliance.",
"Lead development in core functionality, including front and back-end logic and deterministic decision flows styled with Emotion."
],
"links": [
{
"type": "external",
"url": "https://web.engr.oregonstate.edu/~hessro/teaching/hof/cs494#w22",
"label": "CS 494 Hall of Fame"
},
{
"type": "github",
"url": "https://github.com/tylertitsworth/ai-character-generator"
}
]
},
{
"title": "iOS Gesture Alphabet with Swift and CoreML",
"descriptions": [
"iOS keyboard extension that translates movements made by the users phone to corresponding letters using CoreML. Developed as an accessibility solution for users who struggle with traditional keyboards.",
"SCRUM team lead. Collected, cleaned, trained, and tested the model. Developed core translation logic and interface."
],
"links": [
{
"type": "github",
"url": "https://github.com/kjiroux/iOS-Gesture-Alphabet"
}
]
},
{
"title": "Android Mobile App with Backend PokeAPI and Java",
"descriptions": [
"Created 'UltimateDex', a complete Pokedex app accessing the PokeAPI. Users can search, filter, and save entries, with each entry displaying comprehensive information styled to match the series."
],
"links": [
{
"type": "github",
"url": "https://github.com/osu-cs492-w20/final-project-tamagucci/"
}
]
},
{
"title": "NodeJS WebApp with MYSQL Database and Handlebars",
"descriptions": [
"Fantasy task-assignment system utilizing MYSQL to manage guilds, 'quests', and members. NodeJS for backend, Handlebars for templating."
],
"links": [
{
"type": "github",
"url": "https://github.com/yanyan2019/cs340_project/"
}
]
}
]

View File

@ -1,17 +0,0 @@
[
"C# / C++ / C",
"ASP.NET / .NET Core",
"Blazor WASM",
"React",
"Java",
"JavaScript",
"HTML / CSS",
"SQL / MYSQL / MSSQL",
"JSON / XML",
"Python",
"Swift",
"TypeScript",
"MATLAB",
"R",
"LaTeX"
]

View File

@ -1,17 +0,0 @@
[
"MS Visual Studio 2022",
"Git / GitHub / GitLab",
"RESTful API",
"Docker",
"Terraform",
"Jira",
"Linux / UNIX",
"SQL / MYSQL / MSSQL",
"Unreal Engine",
"Unity",
"Blendr",
"Windows, Android & iOS",
"Gephi",
"Excel / Microsoft Office Suite",
"Figma"
]

View File

@ -1,24 +0,0 @@
[
{
"title": "Junior Web Developer",
"company": "Universal Flight Concepts",
"startYear": 2022,
"endYear": 2024,
"details": "Part of a development team that worked on a full rewrite of a 'Secure Area' used by Admin, Students, Instructors and University coordinators to schedule flight and ground instruction, and took the application from ASP.Net 4.0/SQL Server 2016 to a stand-alone C# .Net Core 8, with Blazor WASM (Web Assembly) Microservices API, Identity Server integration, SQL Server 2019, Code-First Entity Framework & DB Migrations, Auto-Scaling Cloud Application"
},
{
"title": "Web Development & Cybersecurity Teaching Assistant",
"company": "Oregon State University",
"startYear": 2019,
"endYear": 2020,
"details": "Interacted with and mentored students with relation to their area of study; created solutions to development projects before being assigned to students to ensure guidance and engrain best coding practices; held personal office hours to assist students mwith needs. HTML/CSS, C++, JavaScript, JSON, Node.js, RESTFUL API, MYSQL; public/private keys, key exchange, modern encryption methods, cyberattacks, TOR."
},
{
"title": "Junior Web Developer",
"company": "DzyneFX",
"startYear": 2018,
"endYear": 2018,
"details": "Developed front-end UI and code for websites, as well as back-end code, data access layers, web services and RESTful APIs. Worked with symmetric and asymmetric data schemas. Request, register and configure SSL and TLS certificates. C#, PHP, MSSQL and MYSQL."
}
]

View File

@ -1,19 +0,0 @@
window.getScreenWidth = () => {
return window.innerWidth;
};
window.registerResizeCallback = (dotNetHelper) => {
window.onresize = () => {
dotNetHelper.invokeMethodAsync('UpdateScreenWidth', window.innerWidth);
};
};
window.downloadFileFromText = (filename, contentType, content) => {
const blob = new Blob([content], { type: contentType });
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = filename;
anchor.click();
URL.revokeObjectURL(url);
}