Compare commits

...

14 Commits

Author SHA1 Message Date
Kira Jiroux 2de78488a9 Updated Pokemon Entity to Accept Skills, SleepStyles, configuring Types with Berries 2025-12-05 13:13:23 -05:00
Kira Jiroux 8d436e659a And now we are accepting Ingredient Edits! 2025-12-04 12:42:03 -05:00
Kira Jiroux 7b6df6530c We are now saving Ingredients! 2025-12-04 12:36:55 -05:00
Kira Jiroux 3feacfaa96 Updated Pokemon Entity to allow for Ingredients. Created Ingredients and Type/Berry json data. Updated badges. Faulty add ingredients, needs work! 2025-11-17 12:45:11 -05:00
Kira Jiroux 1daad24db7 Minor changes to Edit page to make it centered 2025-10-01 12:20:38 -04:00
Kira Jiroux 40a79f1191 Modified Pokemon Sleep Home Page to serve responsive pages at different screen sizes 2025-09-30 19:08:48 -04:00
Kira Jiroux e45d80143c Just needed to update url extensions. Back to responsive styling 2025-09-30 17:57:01 -04:00
Kira Jiroux f10e2941ab Needed to change individual pokemon routing 2025-09-26 14:09:44 -04:00
Kira Jiroux 7f54f5b479 Minor edit 2025-09-26 14:00:46 -04:00
Kira Jiroux 84aeec64e8 Ugh its so so so good 2025-09-26 13:54:32 -04:00
Kira Jiroux 22a6e68fbd Wow I think it's pretty (for desktop). Need to push now before I push it too far 2025-09-26 13:35:48 -04:00
Kira Jiroux 2f210a0e1a Fixed the PokemonSelector visual issue where filtered pokemon appear super spaced out; now they appear naturally. Additional changes are just removing minor things. 2025-09-24 15:13:20 -04:00
Kira Jiroux 37d8fdaca2 Made form slightly better by activating it onchange rather than by onclick. Much more responsive, not absolutely certain it works. But! did put back in a pseudo delete button. It works, but not perfect. 2025-09-23 17:17:25 -04:00
Kira Jiroux 286b913832 Made reusable PokemonForm to replace Add/Edit forms. Also, renamed Download button to better fit the schema. Plus additional decorative changes. 2025-09-23 16:42:40 -04:00
63 changed files with 2500 additions and 1012 deletions

View File

@ -0,0 +1,15 @@
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,12 +13,18 @@ namespace Portfolio.Domain.Features.Pokemon
public required string PokemonName { get; set; }
public bool IsVariation { get; set; } = false;
public string? VariationName { get; set; }
public string? PokemonType { get; set; }
public required string PokemonType { get; set; }
public required string SleepType { 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? PokemonShinyImageUrl { get; set; }
public string[]? PokemonSleepStyleImageUrls { get; set; }
public string? FlavorText { get; set; }
public string? Ingredient1 { get; set; }
public string? Ingredient2 { get; set; }
public string? Ingredient3 { get; set; }
}

View File

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

@ -0,0 +1,130 @@
// <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

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

@ -0,0 +1,136 @@
// <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

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

@ -0,0 +1,149 @@
// <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

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

@ -0,0 +1,146 @@
// <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

@ -0,0 +1,28 @@
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,6 +32,15 @@ namespace Portfolio.Infrastructure.Migrations
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");
@ -48,7 +57,17 @@ namespace Portfolio.Infrastructure.Migrations
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")

View File

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

@ -8,10 +8,8 @@
}
else
{
<h3 class="text-xl font-bold mb-4 mt-4">Temperature Blanket Visualizer</h3>
<div>
<div class="container">
<h3 class="text-xl font-bold mb-4 mt-4">Temperature Blanket Visualizer</h3>
<div class="row">
<div class="col-10">
<div class="d-flex">
@ -26,7 +24,7 @@
</div>
</div>
</div>
<div class="col">
<div class="col d-flex align-items-center">
<TemperatureRangeEditor TempRanges="@TemperatureRanges" OnRangesChanged="HandleRangesChanged" />
</div>
</div>

View File

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

View File

@ -1,152 +0,0 @@
@inject IPokemonService PokemonService
<div class="create-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"
class="form-control "
type="number" />
<InputText placeholder="Pokemon Name"
id="PokemonName"
@bind-Value="NewPokemon.PokemonName"
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"
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"
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" class="form-select rounded-end">
<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="NewPokemon.SleepType" 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" 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>
<!-- <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" 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" 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" 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-primary rounded p-1 px-0"
@onclick="@SendPokemon"
disabled="@( !IsComplete )">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-arrow-up" viewBox="0 0 16 16">
<path d="M8 11a.5.5 0 0 0 .5-.5V6.707l1.146 1.147a.5.5 0 0 0 .708-.708l-2-2a.5.5 0 0 0-.708 0l-2 2a.5.5 0 1 0 .708.708L7.5 6.707V10.5a.5.5 0 0 0 .5.5" />
<path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1" />
</svg>
</button>
@if(mostRecentForm)
{
<button type="button"
class="btn btn-danger rounded p-1 px-0"
@onclick="@HandleRemove">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-file-minus" viewBox="0 0 16 16">
<path d="M5.5 8a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1H6a.5.5 0 0 1-.5-.5" />
<path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1" />
</svg>
</button>
}
</div>
</EditForm>
</div>

View File

@ -1,101 +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;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
public partial class PokemonAddForm
{
[Parameter]
public EventCallback<Pokemon> OnPokemonReady { get; set; }
[Parameter]
public EventCallback RemoveForm { get; set; }
[Parameter]
public bool mostRecentForm { get; set; }
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 bool HideLabel { get; set; } = true;
private bool showErrors { get; set; } = false;
private Pokemon NewPokemon = new Pokemon
{
PokemonId = 0, // Or any default ID logic
PokemonName = string.Empty, // Required fields cannot be null
SleepType = string.Empty,
Speciality = string.Empty,
IsVariation = false
};
private void Toggle() => HideLabel = !HideLabel;
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()
{
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
};
await OnPokemonReady.InvokeAsync(copy);
}
}
}

View File

@ -1,4 +1,11 @@
.badge {
$width: 200px;
$height: 80px;
*, *::before, *::after {
box-sizing: border-box;
}
.badge {
display: flex;
align-items: center;
justify-content: center;
@ -9,9 +16,14 @@
color: white;
font-size: clamp(0.7rem, 1vw, 0.9rem);
text-align: center;
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 {
margin: 0;
padding: 0;

View File

@ -22,11 +22,8 @@
</div>
<!-- Pokemon Image -->
<div class="flip-container z-1" @onclick="() => ToggleImage()">
<div class="flipper @(isShiny ? "flipped" : "")">
<img class="pokemon-image front" src="@_pokemon.PokemonImageUrl" />
<img class="pokemon-image back" src="@_pokemon.PokemonShinyImageUrl" />
</div>
<div class="card-image-slot z-1">
<PokemonImage baseUrl="@_pokemon.PokemonImageUrl" shinyUrl="@_pokemon.PokemonShinyImageUrl" />
</div>
<!-- Pokemon Flavortext -->
@ -53,7 +50,7 @@
</div>
<div class="mt-3">
<div class="mt-5">
<PokemonEditButton PokemonId="@_pokemon.Id" />
</div>
</div>

View File

@ -1,4 +1,11 @@
.pokemon-card {
.card-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.pokemon-card {
position: relative;
width: 100%;
max-width: 350px; /* Prevent it from getting too huge */
@ -20,14 +27,6 @@
transform: translateY(-13px);
}
.card-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.pokemon-name {
position: absolute;
top: 5%;
@ -51,14 +50,8 @@
right: 2%;
width: clamp(1.5rem, 2.5vw, 2.5rem);
height: clamp(1.5rem, 2.5vw, 2.5rem);
}
.pokemon-image {
width: 100%; /* Look to flip-container for the width/height of image */
height: 100%;
position: absolute;
top: 0;
left: 0;
box-shadow: 0 1px 2px 1px rgba(0,0,0,0.35);
border-radius: 20px;
}
.pokemon-flavor-text {
@ -95,45 +88,18 @@
hyphens: auto;
}
.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);
}
.front, .back {
width: 100%;
height: 100%;
/* Position the image area within the card */
.card-image-slot {
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
top: 50%;
left: 50%;
transform: translate(-50%, -20%);
width: 100%;
aspect-ratio: 1 / 1;
max-width: 300px;
}
.back {
transform: rotateY(180deg);
}
/* Type Card Styling */

View File

@ -5,7 +5,7 @@ using System.Text.Json;
namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
partial class PokemonDownload
partial class PokemonDownloadButton
{
[Parameter]
public List<Pokemon> _Pokemon { get; set; }

View File

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

View File

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

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

@ -8,10 +8,8 @@ $display-font-sizes: (
6: 2.5rem
);
.create-container {
.pokemon-form-container {
position: relative;
width: 100%;
max-width: 390px; /* Prevent it from getting too huge */
aspect-ratio: 3 / 4; /* Maintains card shape dynamically */
background-color: var(--bg-color);
border-width: .5rem;
@ -24,5 +22,4 @@ $display-font-sizes: (
.checkbox-styling {
width: 100px;
height: 100px;
}

View File

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

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

@ -0,0 +1,50 @@
.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,18 +1,9 @@

<!-- Heading + Buttons -->
<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">
<!-- Pokemon Navigation Buttons -->
<div class="mx-auto w-75 top-row row" >
<div class="row btn-group d-flex justify-content-end" >
<!-- Home -->
<button class="btn btn-primary mx-1 align-content-center" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemonsleep">
<NavLink href="/pokemon-sleep">
<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">
<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" />
@ -22,7 +13,7 @@
<!-- Pokemon Table-->
<button class="btn btn-info mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemon">
<NavLink href="/pokemon-sleep/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">
<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>
@ -31,7 +22,7 @@
<!-- Rate Pokemon -->
<button class="btn btn-success mx-1" style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/rate-pokemon">
<NavLink href="/pokemon-sleep/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">
<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" />
@ -41,7 +32,7 @@
<!-- Add Pokemon (Wrap in Auth) -->
<button class="btn btn-warning mx-1 " style="border-radius: 50px 15px; max-width: 60px;">
<NavLink href="/pokemonsleep/add-new-pokemon">
<NavLink href="/pokemon-sleep/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">
<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>
@ -49,6 +40,4 @@
</button>
</div>
</div>
</div>

View File

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

View File

@ -1,16 +1,16 @@

<!-- Search Input -->
<div class="pokemon-selector p-3 bg-light">
<input class="form-control mb-3" placeholder="Search Pokémon..." @bind="SearchTerm" @oninput="HandleSearch" />
<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">
<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")"
<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">
@ -21,7 +21,3 @@
}
</div>
</div>
<style>
</style>

View File

@ -5,11 +5,13 @@
border-radius: 5% / 3.5%;
display: flex;
flex-direction: column;
}
.pokemon-grid {
flex: 1 1 auto;
overflow-y: auto;
align-content: flex-start;
}
@ -19,7 +21,7 @@
}
.pokemon-card:hover {
transform: scale(1.05);
transform: scale(1.13);
}
.small-card {

View File

@ -5,55 +5,52 @@
@attribute [StreamRendering]
@rendermode InteractiveServer
<div class="d-flex justify-content-end">
</div>
<!-- Table A: Desktop View-->
<div class="container d-none d-md-block " style="height: 70vh;">
<div class="container d-none d-lg-block d-md-none mt-4">
<!-- Main UI -->
<div class="border-0 mt-4 mx-auto col-12 col-md-10 col-lg-8 pokemontable ">
<!-- Table Header -->
<div class="row bg-secondary bg-gradient py-3 border-0">
<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 align-items-center justify-content-between w-100 position-relative px-3">
<!-- Left: Search -->
<input class="form-control w-25 me-3"
<input class="form-control w-25 me-3 rounded rounded-5"
placeholder="Search Pokémon..."
@bind="SearchTerm"
@oninput="HandleSearch" />
<!-- Center: Title -->
<h2 class="text-white text-decoration-underline mb-0 position-absolute start-50 translate-middle-x">
<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-info">
<p class="statText mb-0">@(pokemons.Count()) Pokémon</p>
<div class="badge bg-light">
<p class="statText text-primary fw-medium shadow mb-0">@(pokemons.Count()) Pokémon</p>
</div>
<PokemonDownload _Pokemon="pokemons" />
<PokemonDownloadButton _Pokemon="pokemons" />
</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 class="">
<tr class="">
<th class="text-white text-bg-info col-2 d-none d-md-table-cell" scope="col"></th>
<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-2 text-center" scope="col">Sleep Type</th>
<th class="text-white text-bg-info col-2 text-center" scope="col">Speciality</th>
<th class="text-white text-bg-info col-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-1 text-center" scope="col">Edit</th>
<th class="text-white text-bg-info col-2 text-center" scope="col">Admin</th>
}
</tr>
@ -68,84 +65,61 @@
else
{
<!-- Table Body -->
<tbody class="">
<tr></tr>
<tbody>
@if (FilteredPokemon != null && FilteredPokemon.Any())
{
@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)
{
<div class="flip-container">
<div class="flipper">
<img class="front img-fluid" style="max-width: 100px;" src="@baseUrl" />
</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>
}
<tr>
<!-- Section 1: Pokemon Image -->
<td class="pokeimage">
<PokemonImage baseUrl="@pokemon.PokemonImageUrl" shinyUrl="@pokemon.PokemonShinyImageUrl" />
</td>
<!-- Section 2: Pokemon # -->
<th class="" scope="row" style="cursor: default;">@pokemon.PokemonId</th>
<th scope="row" style="cursor: default;">@pokemon.PokemonId</th>
<!-- Section 3: Pokemon Name -->
<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 -->
<td class="">
<td>
<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;box-shadow: 0 1px 2px 1px rgba(0,0,0,0.35);border-radius: 20px;" />
</div>
</td>
<!-- Section 5: Sleep Type -->
<td class="" style="">
<td>
<div class="d-flex justify-content-center ">
<PokemonBadge BadgeItem="@pokemon.SleepType" />
</div>
</td>
<!-- Section 6: Speciality -->
<td class="" style="">
<td>
<div class="d-flex justify-content-center">
<PokemonBadge BadgeItem="@pokemon.Speciality" />
</div>
</td>
<!-- Section 7: Admin Controls -->
@if (adminToggle)
{
<td class="" style="">
<div class="d-flex justify-content-center">
<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>
}
}
@ -176,69 +150,223 @@
</div>
</div>
<!-- Desktop B: Mobile View -->
<div class="container card border-0 d-block d-md-none mx-auto mt-4 shadow-sm">
<!-- Table Header -->
<div class="row card-header bg-secondary bg-gradient ml-0 py-3 border-0 bg-info">
<div class="flex-row justify-content-between">
<div class="text-center position-relative">
<h2 class="text-white text-decoration-underline">Pokémon</h2>
<div class="m-1 badge bg-white text-info position-absolute top-0 end-0 border-0 w-auto"><p class="statText">@(pokemons.Count()) Pokémon</p></div>
<div 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>
</div>
<!-- Table Body -->
<div class="tableFixHead row">
<table class="table table-striped border-0">
<!-- 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>
<tbody>
@if (pokemons == null)
{
<Loading />
}
else
{
@foreach (var pokemon in pokemons)
{
<tr class="border-0">
<div class="d-flex align-items-center">
<!-- Pokemon Image -->
<div class="me-3">
<div class="flip-container-sm" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper-sm @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" src="@pokemon.PokemonImageUrl" />
@if (pokemon.PokemonShinyImageUrl != null)
{
<img class="back img-fluid" src="@pokemon.PokemonShinyImageUrl" />
}
</div>
</div>
</div>
<div class="">
<!-- Number and Name -->
<h5>
@pokemon.PokemonId -
<span class="pokemon-name-style fw-light" @onclick="() => ViewPokemon(pokemon.PokemonId)">
@(pokemon.IsVariation && ToggleVariationName(pokemon.Id, pokemon.PokemonId) ? $"{pokemon.VariationName} {pokemon.PokemonName}" : pokemon.PokemonName)
</span>
</h5>
<!-- Stats -->
<div class="d-flex flex-wrap align-items-center gap-2">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:28px;" />
<PokemonBadge BadgeItem="@pokemon.SleepType" />
<PokemonBadge BadgeItem="@pokemon.Speciality" />
</div>
</div>
</div>
}
</tr>
</thead>
<!-- If/Else Pokemon Loaded-->
@if (pokemons == null)
{
<tbody>
<Loading />
</tbody>
}
}
</tbody>
</table>
else
{
<!-- Table Body -->
<tbody>
@if (FilteredPokemon != null && FilteredPokemon.Any())
{
@foreach (var pokemon in FilteredPokemon)
{
<tr>
<!-- Section 1: Pokemon Image -->
<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">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:36px; height:36px;" />
</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>
<!-- Desktop B: Mobile View -->
@* <div class="container card border-0 d-block d-md-none mx-auto mt-4 shadow-sm">
<!-- Table Header -->
<div class="row card-header bg-secondary bg-gradient ml-0 py-3 border-0 bg-info">
<div class="flex-row justify-content-between">
<div class="text-center position-relative">
<h2 class="text-white text-decoration-underline">Pokémon</h2>
<div class="m-1 badge bg-white text-info position-absolute top-0 end-0 border-0 w-auto"><p class="statText">@(pokemons.Count()) Pokémon</p></div>
</div>
</div>
</div>
<!-- Table Body -->
<div class="tableFixHead row">
<table class="table table-striped border-0">
<tbody>
@if (pokemons == null)
{
<Loading />
}
else
{
@foreach (var pokemon in pokemons)
{
<tr class="border-0">
<div class="d-flex align-items-center" style="border: 1px dashed hotpink;">
<!-- Pokemon Image -->
<div class="me-3" style="border: 1px dashed hotpink;">
<div class="flip-container-sm" @onclick="() => ToggleImage(pokemon.Id)">
<div class="flipper-sm @(isShiny[pokemon.Id] ? "flipped" : "")">
<img class="front img-fluid" src="@pokemon.PokemonImageUrl" />
@if (pokemon.PokemonShinyImageUrl != null)
{
<img class="back img-fluid" src="@pokemon.PokemonShinyImageUrl" />
}
</div>
</div>
</div>
<div style="border: 1px dashed hotpink;">
<!-- Number and Name -->
<h5>
@pokemon.PokemonId -
<span class="pokemon-name-style fw-light" @onclick="() => ViewPokemon(pokemon.PokemonId)">
@(pokemon.IsVariation && ToggleVariationName(pokemon.Id, pokemon.PokemonId) ? $"{pokemon.VariationName} {pokemon.PokemonName}" : pokemon.PokemonName)
</span>
</h5>
<!-- Stats -->
<div class="d-flex flex-wrap align-items-center gap-2">
<img src="@GetTypeImageUrl(pokemon.PokemonType)" style="width:28px;" />
<PokemonBadge BadgeItem="@pokemon.SleepType" />
<PokemonBadge BadgeItem="@pokemon.Speciality" />
</div>
</div>
</div>
</tr>
}
}
</tbody>
</table>
</div>
</div> *@

View File

@ -11,9 +11,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
[Parameter]
public List<Pokemon> AllPokemon { get; set; }
private List<Pokemon> pokemons = new List<Pokemon>();
private Dictionary<int, bool> isShiny = new Dictionary<int, bool>();
private bool adminToggle = false;
@ -23,10 +21,6 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
if (AllPokemon != null) {
pokemons = AllPokemon.ToList();
foreach (var pokemon in pokemons)
{
isShiny[pokemon.Id] = false;
}
}
}
private string SearchTerm { get; set; } = string.Empty;
@ -41,13 +35,6 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
{
SearchTerm = e?.Value?.ToString() ?? "";
}
private void ToggleImage(int Id)
{
if (isShiny.ContainsKey(Id))
{
isShiny[Id] = !isShiny[Id];
}
}
private bool ToggleVariationName(int Id, int PokemonId)
{
@ -79,12 +66,12 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
private void EditPokemon(int id)
{
Navigation.NavigateTo($"/pokemonsleep/edit/{id}");
Navigation.NavigateTo($"/pokemon-sleep/edit/{id}");
}
private void ViewPokemon(int id)
{
Navigation.NavigateTo($"/pokemon/{id}");
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{id}");
}
private string GetTypeImageUrl(string pokemonType)
@ -96,6 +83,7 @@ namespace Portfolio.WebUI.Server.Components.Component.Pokemon_Components
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,12 +1,13 @@
.five-percent {
width: 5%;
}
.ten-percent {
width: 10%;
}
.pokemontable {
height: 69vh;
height: 65vh;
}
.tableFixHead {
@ -25,7 +26,7 @@
}
.pokemon-name-style {
cursor:pointer;
cursor: pointer;
font-size: 1.3rem;
}
@ -87,28 +88,6 @@
}
.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);
}
.badge {
width: 100px;
@ -129,5 +108,15 @@
cursor: default;
}
.pokeimage {
width: 100px;
height: 130px;
}

View File

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

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

View File

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

<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,11 +1,9 @@
@inherits LayoutComponentBase
<div class="page">
<main class="">
<NavMenu3 />
<div class="container">
@Body
</div>
<div class="d-flex flex-column min-vh-100">
<BaseNavMenu />
<main class="container flex-grow-1">
@Body
</main>
@* <MadeWithLoveFooter/> *@
<MadeWithLoveFooter/>
</div>

View File

@ -1,8 +1,4 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
@ -12,6 +8,10 @@ main {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.container {
max-width: 1920px;
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
@ -47,9 +47,6 @@ main {
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
@ -76,21 +73,3 @@ 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="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">Portfolio.WebUI.Server</a>
<div class="navbar navbar-expand bg-primary border-0">
<div class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-light text-decoration-none px-3">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#FFFFFF" class="bi bi-arrow-through-heart" viewBox="0 0 16 16" style="cursor: pointer;">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l.53-.53c-.771-.802-1.328-1.58-1.704-2.32-.798-1.575-.775-2.996-.213-4.092C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182a22 22 0 0 1-2.685-2.062l-.539.54V14a.5.5 0 0 1-.146.354zm2.893-4.894A20.4 20.4 0 0 0 8 12.71c2.456-1.666 3.827-3.207 4.489-4.512.679-1.34.607-2.42.215-3.185-.817-1.595-3.087-2.054-4.346-.761L8 4.62l-.358-.368c-1.259-1.293-3.53-.834-4.346.761-.392.766-.464 1.845.215 3.185.323.636.815 1.33 1.519 2.065l1.866-1.867a.5.5 0 1 1 .708.708z" />
</svg>
<span class="fs-4 mx-2 text-white">Kira Jiroux</span>
</div>
</div>
<ul class="navbar-nav">
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
<li class="nav-item">
<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">
<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-white">Home</span>
</NavLink>
</div>
<div class="nav-item px-3">
<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
</li>
<li>
<NavLink class="nav-link d-flex align-items-center" href="temperature-blanket">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFFFFF" class="bi bi-border-outer" viewBox="0 0 16 16">
<path d="M7.5 1.906v.938h1v-.938zm0 1.875v.938h1V3.78h-1zm0 1.875v.938h1v-.938zM1.906 8.5h.938v-1h-.938zm1.875 0h.938v-1H3.78v1zm1.875 0h.938v-1h-.938zm2.813 0v-.031H8.5V7.53h-.031V7.5H7.53v.031H7.5v.938h.031V8.5zm.937 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zM7.5 9.406v.938h1v-.938zm0 1.875v.938h1v-.938zm0 1.875v.938h1v-.938z" />
<path d="M0 0v16h16V0zm1 1h14v14H1z" />
</svg><span class="mx-2 mt-0 text-white">Crochet</span>
</NavLink>
</div>
<div class="nav-item px-3">
<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">
</li>
<li>
<NavLink class="nav-link d-flex align-items-center" 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">
<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
</svg> <span class="mx-2 mt-0 text-white">Pokémon Sleep</span>
</NavLink>
</div>
</nav>
</div>
</li>
</ul>
</div>

View File

@ -1,105 +0,0 @@
.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

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

@ -1,35 +0,0 @@
<div class="navbar navbar-expand bg-primary border-0">
<div class="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-light text-decoration-none px-3">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#FFFFFF" class="bi bi-arrow-through-heart" viewBox="0 0 16 16" style="cursor: pointer;">
<path fill-rule="evenodd" d="M2.854 15.854A.5.5 0 0 1 2 15.5V14H.5a.5.5 0 0 1-.354-.854l1.5-1.5A.5.5 0 0 1 2 11.5h1.793l.53-.53c-.771-.802-1.328-1.58-1.704-2.32-.798-1.575-.775-2.996-.213-4.092C3.426 2.565 6.18 1.809 8 3.233c1.25-.98 2.944-.928 4.212-.152L13.292 2 12.147.854A.5.5 0 0 1 12.5 0h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.854.354L14 2.707l-1.006 1.006c.236.248.44.531.6.845.562 1.096.585 2.517-.213 4.092-.793 1.563-2.395 3.288-5.105 5.08L8 13.912l-.276-.182a22 22 0 0 1-2.685-2.062l-.539.54V14a.5.5 0 0 1-.146.354zm2.893-4.894A20.4 20.4 0 0 0 8 12.71c2.456-1.666 3.827-3.207 4.489-4.512.679-1.34.607-2.42.215-3.185-.817-1.595-3.087-2.054-4.346-.761L8 4.62l-.358-.368c-1.259-1.293-3.53-.834-4.346.761-.392.766-.464 1.845.215 3.185.323.636.815 1.33 1.519 2.065l1.866-1.867a.5.5 0 1 1 .708.708z" />
</svg>
<span class="fs-4 mx-2 text-white">Kira Jiroux</span>
</div>
<ul class="navbar-nav">
<li class="nav-item">
<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">
<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-white">Home</span>
</NavLink>
</li>
<li>
<NavLink class="nav-link d-flex align-items-center" href="temperature-blanket">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#FFFFFF" class="bi bi-border-outer" viewBox="0 0 16 16">
<path d="M7.5 1.906v.938h1v-.938zm0 1.875v.938h1V3.78h-1zm0 1.875v.938h1v-.938zM1.906 8.5h.938v-1h-.938zm1.875 0h.938v-1H3.78v1zm1.875 0h.938v-1h-.938zm2.813 0v-.031H8.5V7.53h-.031V7.5H7.53v.031H7.5v.938h.031V8.5zm.937 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zm1.875 0h.938v-1h-.938zM7.5 9.406v.938h1v-.938zm0 1.875v.938h1v-.938zm0 1.875v.938h1v-.938z" />
<path d="M0 0v16h16V0zm1 1h14v14H1z" />
</svg><span class="mx-2 mt-0 text-white">Crochet</span>
</NavLink>
</li>
<li>
<NavLink class="nav-link d-flex align-items-center" 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">
<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>
</NavLink>
</li>
</ul>
</div>

View File

@ -7,7 +7,7 @@
<PageTitle>Home</PageTitle>
<!-- View 1: Desktop View -->
<div class="container d-none d-lg-none d-xl-block mt-5 pt-3 pb-5 ps-5 pe-5 ">
<div class="container d-none d-lg-none d-xl-block mt-3 pt-3 pb-5 ps-5 pe-5 ">
<h1 class="fst-italic fw-light fs-1 font-monospace">Hello, World!</h1>
<!-- Start of Grid -->
@ -29,7 +29,7 @@
<div class="row">
<!-- School Experience -->
<div class="col-auto ps-0">
<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>
@ -73,7 +73,7 @@
</div>
<!--Skills \ Languages-->
<div class="col p-0 ">
<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>
@ -98,7 +98,7 @@
</div>
<!-- Tools -->
<div class="col pe-0">
<div class="col-auto pe-0">
<div class="bg-white rounded p-2 border border-1 border-primary">
<div class="card-header">

View File

@ -1,18 +1,18 @@
@page "/pokemonsleep/admincontrol"
@page "/pokemon-sleep/admincontrol"
<div class="w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonHeader />
<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="/pokemonsleep/addmincontrol/add-new-pokemon">
<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>

View File

@ -1,4 +1,4 @@
@page "/pokemonsleep/add-new-pokemon"
@page "/pokemon-sleep/add-new-pokemon"
@inject IPokemonService PokemonService
@inject NavigationManager Navigation
@ -10,7 +10,7 @@
<PageTitle>Add New Pokémon</PageTitle>
<PokemonHeader />
<PokemonNavMenu />
@if (isSubmitting)
@ -19,13 +19,14 @@
}
else
{
<div class="container mx-0 px-0">
<div class="row mt-5">
<div class="d-flex justify-content-evenly h-100 p-0">
<div class="container">
<div class="row mt-3">
<div class="d-flex justify-content-evenly p-0">
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonAddForm
<PokemonForm
formUse="ADD"
OnPokemonReady="ReceivePokemon1"
mostRecentForm=false
/>
@ -40,13 +41,15 @@ else
</div>
}
else if (pokemon2FormView && !pokemon3FormView)
{
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonAddForm OnPokemonReady="ReceivePokemon2"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
<PokemonForm OnPokemonReady="ReceivePokemon2"
formUse="ADD"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
</div>
</div>
<div class="mx-1 align-content-center">
@ -54,29 +57,33 @@ else
</div>
}
else if (!pokemon2FormView && pokemon3FormView)
{
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonAddForm OnPokemonReady="ReceivePokemon2"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
<PokemonForm OnPokemonReady="ReceivePokemon2"
formUse="ADD"
RemoveForm="TogglePokemon2FormView"
mostRecentForm="@pokemon2FormView" />
</div>
</div>
<div class="mx-1 align-content-center">
<div class="addcard">
<PokemonAddForm OnPokemonReady="ReceivePokemon3"
RemoveForm="TogglePokemon3FormView"
mostRecentForm="@pokemon3FormView" />
<PokemonForm OnPokemonReady="ReceivePokemon3"
formUse="ADD"
RemoveForm="TogglePokemon3FormView"
mostRecentForm="@pokemon3FormView" />
</div>
</div>
}
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-center">
<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>

View File

@ -25,15 +25,35 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
TogglePokemon2FormView();
}
private Pokemon pokemon1, pokemon2, pokemon3 = new Pokemon
// Create up to 3 Pokemon
private Pokemon pokemon1 = 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 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 ToggleVariationName { get; set; }
@ -42,68 +62,7 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
{
this.ToggleVariationName = true;
}
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");
}
}
else if (pokemon2FormView)
{
if (IsComplete(pokemon1) && IsComplete(pokemon2))
{
await HandleSubmit(pokemon1);
await HandleSubmit(pokemon2);
Navigation.NavigateTo("/pokemon");
}
}
else if (pokemon3FormView)
{
if (IsComplete(pokemon1) && IsComplete(pokemon2) && IsComplete(pokemon3))
{
await HandleSubmit(pokemon1);
await HandleSubmit(pokemon2);
await HandleSubmit(pokemon3);
Navigation.NavigateTo("/pokemon");
}
}
}
private async Task HandleSubmit(Pokemon NewPokemon)
{
isSubmitting = true;
await PokemonService.AddPokemonAsync(NewPokemon);
isSubmitting = false;
}
protected void Cancel(MouseEventArgs e)
{
Console.WriteLine("Testing in Cancel");
Navigation.NavigateTo("/pokemon");
}
private async Task ReceivePokemon1(Pokemon p)
{
@ -140,6 +99,67 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
// 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;
await PokemonService.AddPokemonAsync(NewPokemon);
isSubmitting = false;
}
protected void Cancel(MouseEventArgs e)
{
Console.WriteLine("Testing in Cancel");
Navigation.NavigateTo("/pokemon-sleep/pokemon");
}
}
}

View File

@ -1,10 +1,5 @@
.addcard {
width: 100%;
max-width: 30rem;
flex: 0 0 auto; /* prevent flex shrink/grow */
display: flex;
justify-content: center;
align-items: center;
padding: 0.5rem;
max-width: 25rem;
}

View File

@ -1,133 +1,41 @@
@page "/pokemonsleep/edit/{id:int}"
@page "/pokemon-sleep/edit-pokemon/{id:int}"
@inject IPokemonService PokemonService
@inject NavigationManager Navigation
@inject IJSRuntime JSRuntime
@inject IJSRuntime JS
@attribute [StreamRendering]
@rendermode InteractiveServer
<PageTitle>Edit Pokémon</PageTitle>
<PokemonHeader />
<PokemonNavMenu />
@if (pokemon == null)
{
<p><em>Loading...</em></p>
<Loading />
}
else
{
<!-- Total Componenet-->
<div class="w-50 mt-3 m-auto bg-info edit-container">
<!-- Header -->
<div class="card-header bg-secondary ml-0 py-3 w-100 ">
<div class="row">
<div class="col-12 text-center">
<h2 class="text-info">Edit Pokémon</h2>
<div class="container mt-5 w-50 mb-5">
<div class="row d-flex flex-row mb-0 justify-content-center">
<div class="w-50">
<div class="editcard">
<PokemonForm
formUse="EDIT"
OnPokemonReady="ReceivePokemon"
RemoveForm="Cancel"
mostRecentForm=true
PokemonToEdit="pokemon"
/>
</div>
</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 class="d-flex justify-content-center">
<div class="btn-group">
<button @onclick="@HandleSubmit" class="btn btn-primary rounded">Edit Pokemon</button>
</div>
</div>
}

View File

@ -14,16 +14,28 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
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()
{
await PokemonService.UpdatePokemonAsync(pokemon);
//Navigation.NavigateTo("/pokemonsleep");
await JSRuntime.InvokeVoidAsync("history.back");
await JS.InvokeVoidAsync("history.back");
}
private async void Cancel()
{
await JSRuntime.InvokeVoidAsync("history.back");
await JS.InvokeVoidAsync("history.back");
}

View File

@ -5,3 +5,8 @@
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;
}
.editcard {
width: 100%;
max-width: 30rem;
}

View File

@ -1,4 +1,4 @@
@page "/pokemon/{id:int}"
@page "/pokemon-sleep/pokemon/{id:int}"
@inject IPokemonService PokemonService
@inject NavigationManager Navigation
@ -6,7 +6,7 @@
@rendermode InteractiveServer
<PokemonHeader />
<PokemonNavMenu />
@ -20,7 +20,7 @@ else
<!-- Total Componenet-->
<div class="container">
<div class="w-75 row mt-4 m-auto">
<div class="w-75 lg row mt-5 m-auto">
<!-- Previous Pokemon Button -->
<div class="col-auto">

View File

@ -39,13 +39,13 @@ namespace Portfolio.WebUI.Server.Components.Pages.Pokemon_Pages
private void NavigateToNext()
{
if (_nextPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon/{_nextPokemonId.Value}");
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{_nextPokemonId.Value}");
}
private void NavigateToPrevious()
{
if (_previousPokemonId.HasValue)
Navigation.NavigateTo($"/pokemon/{_previousPokemonId.Value}");
Navigation.NavigateTo($"/pokemon-sleep/pokemon/{_previousPokemonId.Value}");
}
}

View File

@ -1,4 +1,4 @@
@page "/rate-pokemon"
@page "/pokemon-sleep/rate-pokemon"
@inject IPokemonService PokemonService
@inject IPokemonNatureService PokemonNatureService
@ -12,9 +12,9 @@
<PageTitle>Rate Pokémon</PageTitle>
<PokemonHeader />
<PokemonNavMenu />
<div class="mt-4">
<div class="container mt-4">
<div class="row">
@if (PokemonList == null || NatureList == null || SubskillList == null)
{
@ -60,5 +60,4 @@
}
</div>
<hr class="mt-5"/>
</div>

View File

@ -1,4 +1,4 @@
@page "/pokemonsleep"
@page "/pokemon-sleep"
@attribute [StreamRendering]
@ -8,43 +8,48 @@
<PageTitle>Pokémon Sleep</PageTitle>
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonHeader />
<PokemonNavMenu />
<!-- Card -->
<div class="container card shadow-sm border-0 p-3 pb-4 mt-4 m-auto w-75 mb-5 bg-white">
<!-- Large -->
<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-->
<div class="row d-flex flex-row">
<div class="row d-flex flex-row px-3 mb-0 pb-0">
<!-- Image side -->
<div class="col-5 border-0 ">
<img class="shadow-sm w-100 m-auto img-fluid" src="images/Pokemon_Sleep_ID.jpg" />
<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">
<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 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-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">
<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="d-flex justify-content-evenly mt-4 ">
<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">
<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>
@ -53,7 +58,7 @@
</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="/rate-pokemon">
<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" />
@ -65,3 +70,116 @@
</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>

View File

@ -1,4 +1,4 @@
@page "/pokemon"
@page "/pokemon-sleep/pokemon"
@inject IPokemonService PokemonService
@ -10,14 +10,13 @@
<PageTitle>Pokémon Sleep</PageTitle>
<div class="w-100">
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<!-- <PokemonBackground PokemonImages="pokemonImageUrls" ShinyPokemonImages="pokemonShinyImageUrls" /> -->
<PokemonNavMenu />
<PokemonTable AllPokemon="pokemons"/>
<PokemonHeader />
<PokemonTable AllPokemon="pokemons"/>
<hr class="mt-5" />
</div>

View File

@ -0,0 +1,98 @@
[
{
"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

@ -0,0 +1,129 @@
[
{
"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

@ -8,7 +8,7 @@
"links": [
{
"type": "internal",
"url": "/pokemonsleep",
"url": "/temperature-blanket",
"icon": "code"
}
]
@ -22,7 +22,7 @@
"links": [
{
"type": "internal",
"url": "/pokemonsleep",
"url": "/pokemon-sleep",
"icon": "code"
}
]