Add detail game page (#41)
All checks were successful
Game Ideas deploy / build-test-deploy (push) Successful in 1m24s
All checks were successful
Game Ideas deploy / build-test-deploy (push) Successful in 1m24s
Reviewed-on: #41
This commit was merged in pull request #41.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
@page "/Detail/{GameId:int}"
|
||||
@using GameIdeas.BlazorApp.Helpers
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Header
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Interest
|
||||
@using GameIdeas.BlazorApp.Shared.Constants
|
||||
@layout MainLayout
|
||||
|
||||
<HeaderGameIdeas>
|
||||
|
||||
</HeaderGameIdeas>
|
||||
|
||||
<div class="detail-container">
|
||||
<div class="section flex">
|
||||
<a href="" class="square-button">@Icons.Back</a>
|
||||
<h1 class="header-1">@Game.Title</h1>
|
||||
<Interest Value="Game.Interest" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section col-2">
|
||||
<span class="description">@Game.Description</span>
|
||||
|
||||
<div class="medias"></div>
|
||||
</div>
|
||||
|
||||
<div class="section dark col-2">
|
||||
<div class="properties">
|
||||
<h2 class="header-2 grd-col-1">@ResourcesKey.Properties</h2>
|
||||
<div class="pills">
|
||||
@foreach (var property in Game.Properties ?? [])
|
||||
{
|
||||
<div class="pill body-lg">@property.Label</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<h2 class="header-2">@ResourcesKey.Tags</h2>
|
||||
<div class="pills">
|
||||
@foreach (var property in Game.Tags ?? [])
|
||||
{
|
||||
<div class="pill body-lg">@property.Label</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section col-2 first-larger">
|
||||
<div class="additional-informations">
|
||||
<h2 class="header-2">@ResourcesKey.About</h2>
|
||||
<div class="informations">
|
||||
@if (Game.ReleaseDate != null)
|
||||
{
|
||||
<div class="information">
|
||||
<span class="body-sm">@ResourcesKey.ReleaseDate</span>
|
||||
<span class="body-lg">@Game.ReleaseDate?.ToShortDateString()</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Game.StorageSpace != null)
|
||||
{
|
||||
<div class="information">
|
||||
<span class="body-sm">@ResourcesKey.StorageSize</span>
|
||||
<span class="body-lg">@GameHelper.GetFormatedStorageSpace(Game.StorageSpace)</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Game.Developer != null)
|
||||
{
|
||||
<div class="information">
|
||||
<span class="body-sm">@ResourcesKey.Developer</span>
|
||||
<span class="body-lg">@Game.Developer?.Name</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Game.Publisher != null)
|
||||
{
|
||||
<div class="information">
|
||||
<span class="body-sm">@ResourcesKey.Publisher</span>
|
||||
<span class="body-lg">@Game.Publisher?.Name</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="platforms">
|
||||
<h2 class="header-2">@ResourcesKey.Platforms</h2>
|
||||
<div class="pills">
|
||||
@foreach (var platform in Game.Platforms ?? [])
|
||||
{
|
||||
<a class="body-lg pill platform-pill" href="@platform.Url">@platform.Label</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,19 @@
|
||||
using GameIdeas.BlazorApp.Pages.Games.Gateways;
|
||||
using GameIdeas.Shared.Dto;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Pages.Detail;
|
||||
|
||||
public partial class GameDetail
|
||||
{
|
||||
[Inject] private IGameGateway GameGateway { get; set; } = default!;
|
||||
[Parameter] public int GameId { get; set; }
|
||||
|
||||
private GameDetailDto Game = new();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Game = await GameGateway.GetGameById(GameId);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
.detail-container, .properties-tags {
|
||||
display: grid;
|
||||
grid-gap: 20px;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 20px 100px;
|
||||
}
|
||||
|
||||
.col-2 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 40px;
|
||||
}
|
||||
|
||||
.first-larger {
|
||||
grid-template-columns: 3fr 2fr;
|
||||
}
|
||||
|
||||
.dark {
|
||||
background: rgb(0, 0, 0, 0.4)
|
||||
}
|
||||
|
||||
.header-1, .header-2 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.pills, .informations {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 34px;
|
||||
}
|
||||
|
||||
.additional-informations, .platforms {
|
||||
padding: 20px;
|
||||
background: var(--input-secondary);
|
||||
box-shadow: var(--drop-shadow);
|
||||
border-radius: var(--big-radius);
|
||||
}
|
||||
|
||||
.pill {
|
||||
width: fit-content;
|
||||
height: 24px;
|
||||
padding: 0 6px;
|
||||
background: rgb(255, 255, 255, 0.2);
|
||||
border-radius: var(--small-radius);
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.platform-pill {
|
||||
color: var(--violet);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.platform-pill:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.square-button {
|
||||
height: 28px;
|
||||
min-height: 28px;
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
border-radius: var(--small-radius);
|
||||
background: var(--input-primary);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.square-button ::deep svg {
|
||||
fill: var(--white);
|
||||
}
|
||||
|
||||
.square-button:hover ::deep svg {
|
||||
background: var(--input-selected);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
.section {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px) {
|
||||
.col-2 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.platforms {
|
||||
grid-row: 1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@using Blazored.FluentValidation
|
||||
@using GameIdeas.BlazorApp.Shared.Components.CircleLoader
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Select.Models
|
||||
@using GameIdeas.BlazorApp.Shared.Components.SelectSearch
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Slider
|
||||
@using GameIdeas.Shared.Dto
|
||||
@@ -21,16 +22,16 @@
|
||||
<InputNumber TValue="double?" class="storage" @bind-Value=GameDto.StorageSpace />
|
||||
</div>
|
||||
<div class="input-game">
|
||||
<div class="label">@ResourcesKey.Developers :</div>
|
||||
<div class="label">@ResourcesKey.Developer :</div>
|
||||
<SelectSearch TItem="DeveloperDto" Theme="Theme" GetLabel="@(i => i.Name)" QuickAdd=true
|
||||
Items="Categories?.Developers" @bind-Values=GameDto.Developers
|
||||
AddItem="@(str => new DeveloperDto() { Name = str })" />
|
||||
Items="Categories?.Developers" ValuesChanged="HandleDeveloperChanged"
|
||||
AddItem="@(str => new DeveloperDto() { Name = str })" SelectType="SelectType.Single" />
|
||||
</div>
|
||||
<div class="input-game">
|
||||
<div class="label">@ResourcesKey.Publishers :</div>
|
||||
<div class="label">@ResourcesKey.Publisher :</div>
|
||||
<SelectSearch TItem="PublisherDto" Theme="Theme" GetLabel="@(i => i.Name)" QuickAdd=true
|
||||
Items="Categories?.Publishers" @bind-Values=GameDto.Publishers
|
||||
AddItem="@(str => new PublisherDto() { Name = str })" />
|
||||
Items="Categories?.Publishers" ValuesChanged="HandlePublisherChanged"
|
||||
AddItem="@(str => new PublisherDto() { Name = str })" SelectType="SelectType.Single" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
@@ -75,4 +75,12 @@ public partial class GameCreationForm
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
private void HandlePublisherChanged(List<PublisherDto> pubs)
|
||||
{
|
||||
GameDto.Publisher = pubs.FirstOrDefault();
|
||||
}
|
||||
private void HandleDeveloperChanged(List<DeveloperDto> devs)
|
||||
{
|
||||
GameDto.Developer = devs.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
@using GameIdeas.BlazorApp.Helpers
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Interest
|
||||
@using GameIdeas.BlazorApp.Shared.Constants
|
||||
@inherits GameBase
|
||||
|
||||
<div class="row">
|
||||
<img class="icon" src="~/icon.png" />
|
||||
|
||||
<a class="title" href="@($"/Games/Detail/{GameDto.Id}")">@GameDto.Title</a>
|
||||
<a class="title" href="@($"/Detail/{GameDto.Id}")">@GameDto.Title</a>
|
||||
|
||||
<span class="release-date">@(GameDto.ReleaseDate?.ToShortDateString() ?? @ResourcesKey.Unknown)</span>
|
||||
|
||||
@@ -30,12 +31,7 @@
|
||||
|
||||
<span class="storage">@GameHelper.GetFormatedStorageSpace(GameDto.StorageSpace)</span>
|
||||
|
||||
<div class="interest">
|
||||
<span class="value" style="@($"color: var({GameHelper.GetInterestColor(GameDto.Interest, 5)})")">
|
||||
@GameDto.Interest
|
||||
</span>
|
||||
<span class="max-value">/5</span>
|
||||
</div>
|
||||
<Interest Value="GameDto.Interest" />
|
||||
|
||||
<button class="detail">@Icons.Triangle</button>
|
||||
</div>
|
||||
@@ -11,7 +11,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.row * {
|
||||
.row > * {
|
||||
max-height: 64px;
|
||||
height: fit-content;
|
||||
padding: 6px 0;
|
||||
@@ -39,7 +39,7 @@
|
||||
background: var(--input-selected);
|
||||
}
|
||||
|
||||
.release-date, .storage, .max-value {
|
||||
.release-date, .storage {
|
||||
color: rgb(184, 184, 184);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
background: rgb(255, 255, 255, 0.2);
|
||||
border-radius: var(--small-radius);
|
||||
align-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.platforms, .tags {
|
||||
display: flex;
|
||||
@@ -80,16 +80,6 @@
|
||||
fill: var(--white);
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.max-value {
|
||||
position: absolute;
|
||||
transform: translate(2px, 10px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
.row {
|
||||
grid-template-columns: 48px 3fr 2fr 3fr 30px 30px;
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
<SelectSearch TItem="PropertyDto" Placeholder="@ResourcesKey.Properties" GetLabel="@(p => p.Label)"
|
||||
@bind-Values=GameFilter.Properties @bind-Values:after=HandleValueChanged Theme="Theme" Items="Categories?.Properties" />
|
||||
|
||||
<SelectSearch TItem="DeveloperDto" Placeholder="@ResourcesKey.Developers" GetLabel="@(p => p.Name)"
|
||||
<SelectSearch TItem="DeveloperDto" Placeholder="@ResourcesKey.Developer" GetLabel="@(p => p.Name)"
|
||||
@bind-Values=GameFilter.Developers @bind-Values:after=HandleValueChanged Theme="Theme" Items="Categories?.Developers" />
|
||||
|
||||
<SelectSearch TItem="PublisherDto" Placeholder="@ResourcesKey.Publishers" GetLabel="@(p => p.Name)"
|
||||
<SelectSearch TItem="PublisherDto" Placeholder="@ResourcesKey.Publisher" GetLabel="@(p => p.Name)"
|
||||
@bind-Values=GameFilter.Publishers @bind-Values:after=HandleValueChanged Theme="Theme" Items="Categories?.Publishers" />
|
||||
|
||||
<SelectSearch TItem="int" Placeholder="@ResourcesKey.ReleaseDate" GetLabel="@(p => p.ToString())"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/"
|
||||
@using GameIdeas.BlazorApp.Layouts
|
||||
@using GameIdeas.BlazorApp.Pages.Games.Components
|
||||
@using GameIdeas.BlazorApp.Pages.Games.Filter
|
||||
@using GameIdeas.BlazorApp.Shared.Components
|
||||
|
||||
@@ -62,4 +62,18 @@ public class GameGateway(IHttpClientService httpClientService) : IGameGateway
|
||||
throw new GameNotFoundException(ResourcesKey.ErrorFetchGames);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<GameDetailDto> GetGameById(int gameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await httpClientService.FetchDataAsync<GameDetailDto>(Endpoints.Game.FetchById(gameId));
|
||||
|
||||
return result ?? throw new InvalidOperationException(ResourcesKey.ErrorFetchGames);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new CategoryNotFoundException(ResourcesKey.ErrorFetchGames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,5 @@ public interface IGameGateway
|
||||
Task<CategoriesDto> FetchCategories();
|
||||
Task<int> CreateGame(GameDetailDto game);
|
||||
Task<IEnumerable<GameDto>> FetchGames(GameFilterParams filter, int currentPage);
|
||||
Task<GameDetailDto> GetGameById(int gameId);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/Users"
|
||||
@using GameIdeas.BlazorApp.Layouts
|
||||
@using GameIdeas.BlazorApp.Pages.Users.Components
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Header
|
||||
@using GameIdeas.BlazorApp.Shared.Components.Popup
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@using GameIdeas.BlazorApp.Helpers
|
||||
|
||||
<div class="interest">
|
||||
<span class="value" style="@($"color: var({GameHelper.GetInterestColor(Value, 5)})")">
|
||||
@Value
|
||||
</span>
|
||||
<span class="max-value">/5</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GameIdeas.BlazorApp.Shared.Components.Interest;
|
||||
|
||||
public partial class Interest
|
||||
{
|
||||
[Parameter] public int Value { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
.interest {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.value {
|
||||
align-content: center;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.max-value {
|
||||
align-content: center;
|
||||
transform: translate(2px, 10px);
|
||||
color: rgb(184, 184, 184);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ public static class Endpoints
|
||||
{
|
||||
public const string Create = "api/Game/Create";
|
||||
public static string Fetch(GameFilterDto filter) => $"api/Game?{UrlHelper.BuildUrlParams(filter)}";
|
||||
public static string FetchById(int gameId) => $"api/Game/{gameId}";
|
||||
}
|
||||
|
||||
public static class Category
|
||||
|
||||
@@ -39,4 +39,8 @@ public static class Icons
|
||||
public readonly static MarkupString Check = new(OpenBraket +
|
||||
"<path d=\"M9,20.42L2.79,14.21L5.62,11.38L9,14.77L18.88,4.88L21.71,7.71L9,20.42Z\" />" +
|
||||
CloseBraket);
|
||||
|
||||
public readonly static MarkupString Back = new(OpenBraket +
|
||||
"<path d=\"M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z\" />" +
|
||||
CloseBraket);
|
||||
}
|
||||
|
||||
@@ -7,3 +7,4 @@
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http
|
||||
@using Microsoft.JSInterop
|
||||
@using GameIdeas.Resources
|
||||
@using GameIdeas.BlazorApp.Layouts
|
||||
|
||||
@@ -132,6 +132,32 @@ code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.expand-col-2 {
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
|
||||
.expand-row-2 {
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
|
||||
.body-sm {
|
||||
color: #ccc
|
||||
}
|
||||
|
||||
.body-lg {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.header-1, .header-2, span, a {
|
||||
display: block;
|
||||
color: var(--white);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
@keyframes fade-in {
|
||||
0% {opacity: 0}
|
||||
100% {opacity: 1}
|
||||
|
||||
Reference in New Issue
Block a user