mirror of
https://github.com/michivonah/website-v3.git
synced 2025-12-22 13:26:29 +01:00
add link to project cards + implement tag filtering & loader for projects + message when no projects available + fix bugs
This commit is contained in:
parent
52af1a4e01
commit
ba15e71c80
3 changed files with 174 additions and 10 deletions
|
|
@ -2,16 +2,31 @@
|
|||
<h1 class="fade-up">{{ T "projects" }}</h1>
|
||||
<div class="tag-filter fade-up">
|
||||
{{ range .Site.Data.tags }}
|
||||
<div class="tag">
|
||||
<label class="tag" for="tag-{{ .slug }}" >
|
||||
<input class="tag-checkbox" id="tag-{{ .slug }}" value="{{ .slug }}" type="checkbox" {{ if .checked }} checked {{ end }}>
|
||||
<label class="tag-label" for="tag-{{ .slug }}" >{{ .title }}</label>
|
||||
</div>
|
||||
<span class="tag-label">{{ .title }}</span>
|
||||
</label>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="project-list">
|
||||
</div>
|
||||
<div class="fade-up">
|
||||
|
||||
<div class="no-projects">
|
||||
<i class="ai-face-sad"></i>
|
||||
<p>No projects found</p>
|
||||
</div>
|
||||
|
||||
<div class="project-loader-wrapper hidden">
|
||||
<div class="project-loader">
|
||||
<div class="project-loader-circle"></div>
|
||||
<div class="project-loader-circle"></div>
|
||||
<div class="project-loader-circle"></div>
|
||||
<div class="project-loader-circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-load fade-up">
|
||||
<button class="project-load-btn" alt='{{ T "load-more" }}' title='{{ T "load-more" }}' name='{{ T "load-more" }}'>{{ T "load-more" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -110,6 +110,28 @@ function calculateAge(selector){
|
|||
obj.textContent = age;
|
||||
}
|
||||
|
||||
// tag filtering
|
||||
document.querySelectorAll(".tag-checkbox").forEach(element => {
|
||||
element.addEventListener("change", function(){
|
||||
showSelectedProjects(element.value, element.checked);
|
||||
});
|
||||
});
|
||||
|
||||
function showSelectedProjects(category, show = true){
|
||||
if(category){
|
||||
document.querySelectorAll(`.${category}`).forEach(project => {
|
||||
project.classList.toggle("hidden", !show);
|
||||
});
|
||||
}
|
||||
else{
|
||||
console.error("func showSelectedProjects(): Missing category name.");
|
||||
}
|
||||
}
|
||||
|
||||
function isCategoryEnabled(category){
|
||||
return document.querySelector(`#tag-${category}`).checked;
|
||||
}
|
||||
|
||||
// load projects from api
|
||||
// content api: https://api.michivonah.ch/?limit=8&page=1
|
||||
async function loadContent(endpoint = "https://api.michivonah.ch", limit = 6, page = 1){
|
||||
|
|
@ -151,18 +173,24 @@ async function getProjectCard(data){
|
|||
year: "numeric"
|
||||
});
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.title = title;
|
||||
link.alt = title;
|
||||
|
||||
const container = document.createElement("div");
|
||||
container.classList = "project-card fade-up";
|
||||
container.classList.add(category);
|
||||
if(!isCategoryEnabled(category)) container.classList.add("hidden");
|
||||
//container.style.animation = "fade-up var(--baseDuration) linear";
|
||||
//container.style.backgroundImage = `url(${image})`;
|
||||
|
||||
const cardFirst = document.createElement("div");
|
||||
cardFirst.classList = "card-first";
|
||||
const emptyText = document.createElement("p");
|
||||
cardFirst.appendChild(emptyText);
|
||||
const cardImage = document.createElement("img");
|
||||
cardImage.src = image;
|
||||
cardImage.alt = title;
|
||||
cardImage.title = title;
|
||||
cardFirst.appendChild(cardImage);
|
||||
|
||||
const cardSecond = document.createElement("div");
|
||||
|
|
@ -177,8 +205,9 @@ async function getProjectCard(data){
|
|||
cardSecond.appendChild(cardTitle);
|
||||
cardSecond.appendChild(cardDate);
|
||||
|
||||
container.appendChild(cardFirst);
|
||||
container.appendChild(cardSecond);
|
||||
link.appendChild(cardFirst);
|
||||
link.appendChild(cardSecond);
|
||||
container.appendChild(link);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
|
@ -186,18 +215,20 @@ async function getProjectCard(data){
|
|||
async function loadMoreContent(wrapperSelector, amount, endpoint = "https://api.michivonah.ch", btnSelector = ".project-load-btn"){
|
||||
const wrapper = document.querySelector(wrapperSelector);
|
||||
const page = ((wrapper.childElementCount <= 0) ? 1 : (wrapper.childElementCount / amount) + 1);
|
||||
const loader = document.querySelector('.project-loader-wrapper');
|
||||
|
||||
// just for debugging purposes
|
||||
//console.log(`children: ${wrapper.childElementCount} limit: ${amount} page: ${page}`);
|
||||
|
||||
// error validation -> only load more content when page num is valid
|
||||
if (page % 1 == 0){
|
||||
loader.classList.remove('hidden');
|
||||
await showProjects('.project-list', await loadContent(endpoint, amount, page));
|
||||
loader.classList.add('hidden');
|
||||
}
|
||||
else{
|
||||
// hide button if no more content is available
|
||||
//if (event.target.tagName == "BUTTON") event.target.style.display = "none";
|
||||
document.querySelector(btnSelector).style.opacity = 0;
|
||||
document.querySelector(btnSelector).classList.add('hidden');
|
||||
}
|
||||
|
||||
}
|
||||
118
static/style.css
118
static/style.css
|
|
@ -385,6 +385,7 @@ nav.small .nav-links a:last-child:focus{
|
|||
border-radius: var(--baseRadius);
|
||||
transition: var(--baseTransition);
|
||||
border: 2px solid var(--primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag input{
|
||||
|
|
@ -424,6 +425,10 @@ nav.small .nav-links a:last-child:focus{
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.project-load-btn.hidden{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.project-load-btn:hover{
|
||||
padding: 10px 40px;
|
||||
background: var(--secondary);
|
||||
|
|
@ -431,6 +436,27 @@ nav.small .nav-links a:last-child:focus{
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.no-projects{
|
||||
font-size: 1.8rem;
|
||||
font-weight: 600;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.no-projects i{
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
/* show no projects message, when no project exists that isn't hidden and loader is hidden */
|
||||
.project-list:not(:has(.project-card:not(.hidden))) + .no-projects:not(:has(+ .project-loader-wrapper:not(.hidden))){
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* hide load more btn when no projects are shown */
|
||||
.project-list:not(:has(.project-card:not(.hidden))) ~ .project-load .project-load-btn{
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* Card animation: https://uiverse.io/suleymanlaarabidev/perfect-husky-88 */
|
||||
.project-card{
|
||||
width: 30%;
|
||||
|
|
@ -456,6 +482,16 @@ nav.small .nav-links a:last-child:focus{
|
|||
--fontWeightP: 600;
|
||||
}
|
||||
|
||||
.project-card a{
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-style: inherit;
|
||||
}
|
||||
|
||||
.project-card.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card-first img{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
|
|
@ -571,6 +607,88 @@ nav.small .nav-links a:last-child:focus{
|
|||
}
|
||||
}
|
||||
|
||||
/* PROJECTS LOADER */
|
||||
/* credits: https://uiverse.io/AbanoubMagdy1/evil-bullfrog-30 */
|
||||
.project-loader-wrapper{
|
||||
width: 100%;
|
||||
height: calc(var(--size) * 2);
|
||||
margin: 0 0 var(--size) 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
|
||||
--size: 2.5rem;
|
||||
--factor: 2.5;
|
||||
--duration: 2s;
|
||||
}
|
||||
|
||||
.project-loader-wrapper.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.project-loader{
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
position: relative;
|
||||
animation: circleLoader var(--duration) linear infinite;
|
||||
}
|
||||
|
||||
.project-loader-circle{
|
||||
width: calc(var(--size) / var(--factor));
|
||||
height: calc(var(--size) / var(--factor));
|
||||
background: var(--primary);
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.project-loader-circle:nth-child(1){
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.project-loader-circle:nth-child(2){
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.project-loader-circle:nth-child(3){
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.project-loader-circle:nth-child(4){
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@keyframes circleLoader{
|
||||
0%{
|
||||
scale: 1;
|
||||
rotate: 0deg;
|
||||
}
|
||||
|
||||
20%, 25%{
|
||||
scale: 1.3;
|
||||
rotate: 90deg;
|
||||
}
|
||||
|
||||
45%, 50%{
|
||||
scale: 1;
|
||||
rotate: 180deg;
|
||||
}
|
||||
|
||||
70%, 75%{
|
||||
scale: 1.3;
|
||||
rotate: 270deg;
|
||||
}
|
||||
|
||||
95%, 100%{
|
||||
scale: 1;
|
||||
rotate: 360deg;
|
||||
}
|
||||
}
|
||||
|
||||
/* CONTACT */
|
||||
.contact{
|
||||
display: flex;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue