Resolve "Projects Page" #20

Merged
leon.hoppe merged 1 commits from feature/projects-page into dev 2025-01-21 18:31:58 +01:00
9 changed files with 211 additions and 2 deletions

View File

@@ -14,6 +14,9 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/devicon.min.css">
</head>
<body>

View File

@@ -0,0 +1,13 @@
<button type="button" class="button">
@Text
<svg viewBox="0 0 150 40" fill="none" preserveAspectRatio="none">
<rect vector-effect="non-scaling-stroke" height="40" width="150" rx="10" />
</svg>
</button>
@code {
[Parameter]
public required string Text { get; set; }
}

View File

@@ -0,0 +1,54 @@
.button {
position: relative;
width: 150px;
height: 40px;
background-color: transparent;
border: none;
color: var(--text);
font-size: 15px;
border-radius: 10px;
cursor: pointer;
max-width: 100%;
overflow: hidden;
z-index: 1;
&:before {
content: '';
position: absolute;
background-color: hsl(217, 41%, 15%);
border-radius: 50%;
width: 150px;
height: 150px;
transform: scale(0);
transition: transform 200ms ease-in-out;
z-index: -1;
top: 50%;
left: 50%;
translate: -50% -50%;
}
}
button svg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
button rect {
stroke: hsl(0, 0%, 70%);
stroke-dasharray: 460;
stroke-dashoffset: 460;
stroke-width: 2px;
transition: stroke-dashoffset 500ms ease-in-out;
}
button:hover rect {
stroke-dashoffset: 0;
}
button:hover:before {
transform: scale(1);
}

View File

@@ -0,0 +1,45 @@
@using Portfolio.Shared.Models
<div class="border">
<div class="shell">
<img src="@Project.Cover" alt="project-cover">
<h3>@Project.Name</h3>
<div class="info">
<div class="language-container">
@foreach (var language in Project.Languages) {
var imgClass = "devicon-" + language.Identifier + "-" + (!string.IsNullOrEmpty(language.Suffix) ? language.Suffix : "plain");
<i class="@imgClass"></i>
}
</div>
<span class="status">@GetStatusName()</span>
</div>
<p>@Project.Description</p>
<div class="button-container">
<a href="@Project.SourceCode">
<FancyButton Text="Source Code" />
</a>
</div>
</div>
</div>
@code {
[Parameter]
public required Project Project { get; set; }
private string GetStatusName() {
return Project.Status switch {
ProjectStatus.Finished => "Fertig",
ProjectStatus.Canceled => "Abgebrochen",
ProjectStatus.Paused => "Angehalten",
ProjectStatus.Development => "Aktiv",
_ => ""
};
}
}

View File

@@ -0,0 +1,59 @@
.border {
position: relative;
width: 400px;
height: 500px;
background: var(--gradient-straight);
border-radius: 30px;
overflow: hidden;
box-shadow: 0 0 40px -10px var(--primary);
}
.shell {
position: absolute;
inset: 1px;
padding: 1rem;
display: flex;
flex-direction: column;
background-color: var(--background);
border-radius: 30px;
}
img {
width: 100%;
height: 190px;
border-radius: calc(30px - 1rem);
object-fit: cover;
}
h3 {
margin-block: 10px;
font-size: 1.25rem;
font-weight: normal;
}
.status, .language-container i, p {
color: var(--desc-color);
}
.info {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.language-container {
margin-bottom: 10px;
display: flex;
gap: 5px;
font-size: 20px;
}
p {
margin: 0;
}
.button-container {
margin-top: auto;
display: flex;
justify-content: center;
}

View File

@@ -6,6 +6,7 @@
background-color: var(--background);
border-bottom: 1px solid var(--border-color);
padding-inline: 0.5rem;
z-index: 100;
}
.links {

View File

@@ -3,5 +3,3 @@
<PageTitle>Portfolio von Leon Hoppe</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

View File

@@ -0,0 +1,23 @@
@page "/projects"
@using Portfolio.Shared.Models
@using Portfolio.Shared.Services
@using Portfolio.Web.Components.Components
<h2>Alle Projekte</h2>
<div class="project-container">
@foreach (var project in _projects) {
<ProjectView Project="project" />
}
</div>
@inherits CancellableComponent
@inject IProjectRepository ProjectRepo
@code {
private IEnumerable<Project> _projects = [];
protected override async Task OnInitializedAsync() {
_projects = await ProjectRepo.GetProjects(TokenSource.Token);
}
}

View File

@@ -0,0 +1,13 @@
.project-container {
display: flex;
flex-wrap: wrap;
gap: 100px;
justify-content: space-evenly;
}
h2 {
margin-top: 3rem;
margin-bottom: 5rem;
font-size: 2rem;
font-weight: 600;
}