Add the ability to pin games on the games page.
This commit is contained in:
parent
3d45aa6e66
commit
cef106b512
7 changed files with 157 additions and 57 deletions
3
public/img/checkmark.svg
Normal file
3
public/img/checkmark.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16">
|
||||
<path fill="#fff" d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 283 B |
3
public/img/games/pin-outline.svg
Normal file
3
public/img/games/pin-outline.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#fff" d="M21.436 7.586l-3.998-4.02c-.752-.756-2.063-.764-2.83-.006-.196.196-.35.436-.418.629-.653 1.362-1.354 2.215-2.254 2.727l-.217.105c-.968.485-2.285.979-4.719.979-.266 0-.521.052-.766.152-.484.202-.879.595-1.082 1.084-.199.484-.199 1.041 0 1.525.104.249.25.471.435.651l3.235 3.235-3.822 5.353 5.352-3.822 3.227 3.227c.186.189.406.339.656.441.247.103.503.154.766.154s.519-.052.765-.154c.498-.205.883-.592 1.08-1.078.103-.242.155-.507.155-.768 0-2.436.494-3.752.978-4.721.496-.992 1.369-1.748 2.754-2.414.271-.104.51-.256.711-.457.772-.782.768-2.051-.008-2.822zm-5.248 4.801c-.819 1.643-1.188 3.37-1.195 5.604l-7.993-7.991c2.139 0 3.814-.335 5.396-1.084l.235-.105c1.399-.699 2.468-1.893 3.388-3.834l3.924 4.051c-1.863.893-3.056 1.96-3.755 3.359z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 892 B |
3
public/img/games/pin.svg
Normal file
3
public/img/games/pin.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#fff" d="M16.729 4.271c-.389-.391-1.021-.393-1.414-.004-.104.104-.176.227-.225.355-.832 1.736-1.748 2.715-2.904 3.293-1.297.64-2.786 1.085-5.186 1.085-.13 0-.26.025-.382.076-.245.102-.439.297-.541.541-.101.244-.101.52 0 .764.051.123.124.234.217.326l3.243 3.243-4.537 6.05 6.05-4.537 3.242 3.242c.092.094.203.166.326.217.122.051.252.078.382.078s.26-.027.382-.078c.245-.102.44-.295.541-.541.051-.121.077-.252.077-.381 0-2.4.444-3.889 1.083-5.166.577-1.156 1.556-2.072 3.293-2.904.129-.049.251-.121.354-.225.389-.393.387-1.025-.004-1.414l-3.997-4.02z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 691 B |
|
|
@ -2,7 +2,8 @@
|
|||
const { game } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="game" data-name={game.name}>
|
||||
<div class="game" data-name={game.name} data-id={game.slug}>
|
||||
<img class="pin-icon" src="/img/games/pin-outline.svg" />
|
||||
<a class="game-link" href=`/game/${game.slug}`>
|
||||
<img alt={game.name} class="game-img" src={game.image} alt="" />
|
||||
<p class="game-title">{game.name}</p>
|
||||
|
|
@ -11,9 +12,10 @@ const { game } = Astro.props;
|
|||
|
||||
<style>
|
||||
.game {
|
||||
position: relative;
|
||||
background-color: var(--accent-color);
|
||||
border: 2px solid var(--text-color);
|
||||
padding: 1rem;
|
||||
padding: 1.2rem;
|
||||
padding-bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -37,4 +39,13 @@ const { game } = Astro.props;
|
|||
font-size: 18px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.pin-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,21 @@
|
|||
"image": "/games/basketball-stars/logo.png",
|
||||
"slug": "basketball-stars"
|
||||
},
|
||||
"bitlife": {
|
||||
"name": "BitLife",
|
||||
"description": "BitLife is a life simulator that lets you live your life however you want. Make choices that will affect your character's life from birth to death.",
|
||||
"image": "/games/bitlife/logo.png",
|
||||
"slug": "bitlife",
|
||||
"unity": true,
|
||||
"vertical": true
|
||||
},
|
||||
"bloons": {
|
||||
"name": "Bloons",
|
||||
"description": "The first ever bloons game! Pop the balloons with darts and complete the levels. A simple yet surprisingly addictive game.",
|
||||
"image": "/games/flash/img/bloons.webp",
|
||||
"slug": "bloons",
|
||||
"flash": true
|
||||
},
|
||||
"bloons-tower-defense-2": {
|
||||
"name": "Bloons Tower Defense 2",
|
||||
"description": "Bloons Tower Defense 2 is a popular tower defense game originally released in Flash by Ninja Kiwi. Strategically place your defenses, upgrade your units, and stop all balloons from passing through.",
|
||||
|
|
@ -52,13 +67,6 @@
|
|||
"slug": "bloons-tower-defense-4",
|
||||
"flash": true
|
||||
},
|
||||
"bloons": {
|
||||
"name": "Bloons",
|
||||
"description": "The first ever bloons game! Pop the balloons with darts and complete the levels. A simple yet surprisingly addictive game.",
|
||||
"image": "/games/flash/img/bloons.webp",
|
||||
"slug": "bloons",
|
||||
"flash": true
|
||||
},
|
||||
"bloxors": {
|
||||
"name": "Bloxors",
|
||||
"description": "Bloxorz is a tricky puzzle game that tests your logical skills and sheer brain power. The objective is to get the block into the square hole and avoid falling off the edge. Put your brain to the test and see how far you get!",
|
||||
|
|
@ -66,14 +74,6 @@
|
|||
"slug": "bloxors",
|
||||
"flash": true
|
||||
},
|
||||
"bitlife": {
|
||||
"name": "BitLife",
|
||||
"description": "BitLife is a life simulator that lets you live your life however you want. Make choices that will affect your character's life from birth to death.",
|
||||
"image": "/games/bitlife/logo.png",
|
||||
"slug": "bitlife",
|
||||
"unity": true,
|
||||
"vertical": true
|
||||
},
|
||||
"cannon-basketball-4": {
|
||||
"name": "Cannon Basketball 4",
|
||||
"description": "Use your mouse to aim and shoot the cannon. Move your mouse further from the cannon to make a more powerful shot. Use the guide to get a ball into the net with as few attempts as possible!",
|
||||
|
|
@ -274,13 +274,6 @@
|
|||
"slug": "henry-stickman-breaking-the-bank",
|
||||
"flash": true
|
||||
},
|
||||
"henry-stickman-stealing-the-diamond": {
|
||||
"name": "Stealing the Diamond",
|
||||
"description": "Help Henry Stickman steal a diamond from a museum! Choose your path and see how your choices affect the outcome.",
|
||||
"image": "/games/flash/img/stealing-the-diamond.avif",
|
||||
"slug": "henry-stickman-stealing-the-diamond",
|
||||
"flash": true
|
||||
},
|
||||
"henry-stickman-escaping-the-prison": {
|
||||
"name": "Escaping the Prison",
|
||||
"description": "Help Henry Stickman escape from prison! Choose your path and see how your choices affect the outcome.",
|
||||
|
|
@ -288,6 +281,13 @@
|
|||
"slug": "henry-stickman-escaping-the-prison",
|
||||
"flash": true
|
||||
},
|
||||
"henry-stickman-fleeing-the-complex": {
|
||||
"name": "Fleeing the Complex",
|
||||
"description": "Help Henry Stickman flee from a complex! Choose your path and see how your choices affect the outcome.",
|
||||
"image": "/games/flash/img/fleeing-the-complex.avif",
|
||||
"slug": "henry-stickman-fleeing-the-complex",
|
||||
"flash": true
|
||||
},
|
||||
"henry-stickman-infiltrating-the-airship": {
|
||||
"name": "Infiltrating the Airship",
|
||||
"description": "Help Henry Stickman infiltrate an airship! Choose your path and see how your choices affect the outcome.",
|
||||
|
|
@ -295,11 +295,11 @@
|
|||
"slug": "henry-stickman-infiltrating-the-airship",
|
||||
"flash": true
|
||||
},
|
||||
"henry-stickman-fleeing-the-complex": {
|
||||
"name": "Fleeing the Complex",
|
||||
"description": "Help Henry Stickman flee from a complex! Choose your path and see how your choices affect the outcome.",
|
||||
"image": "/games/flash/img/fleeing-the-complex.avif",
|
||||
"slug": "henry-stickman-fleeing-the-complex",
|
||||
"henry-stickman-stealing-the-diamond": {
|
||||
"name": "Stealing the Diamond",
|
||||
"description": "Help Henry Stickman steal a diamond from a museum! Choose your path and see how your choices affect the outcome.",
|
||||
"image": "/games/flash/img/stealing-the-diamond.avif",
|
||||
"slug": "henry-stickman-stealing-the-diamond",
|
||||
"flash": true
|
||||
},
|
||||
"idle-breakout": {
|
||||
|
|
@ -431,12 +431,6 @@
|
|||
"image": "/games/temple-run-2/logo.webp",
|
||||
"slug": "temple-run-2"
|
||||
},
|
||||
"there-is-no-game": {
|
||||
"name": "There is No Game",
|
||||
"description": "There is No Game is a unique interactive experience that plays with the concept of video games. It's a humorous and clever adventure that breaks the fourth wall.",
|
||||
"image": "/games/there-is-no-game/logo.png",
|
||||
"slug": "there-is-no-game"
|
||||
},
|
||||
"the-binding-of-isaac": {
|
||||
"name": "The Binding of Isaac",
|
||||
"description": "When Isaac’s mother starts hearing the voice of God demanding a sacrifice be made to prove her faith, Isaac escapes into the basement facing droves of deranged enemies, lost brothers and sisters, his fears, and eventually his mother.",
|
||||
|
|
@ -444,6 +438,12 @@
|
|||
"slug": "the-binding-of-isaac",
|
||||
"flash": true
|
||||
},
|
||||
"there-is-no-game": {
|
||||
"name": "There is No Game",
|
||||
"description": "There is No Game is a unique interactive experience that plays with the concept of video games. It's a humorous and clever adventure that breaks the fourth wall.",
|
||||
"image": "/games/there-is-no-game/logo.png",
|
||||
"slug": "there-is-no-game"
|
||||
},
|
||||
"tunnelrush": {
|
||||
"name": "Tunnel Rush",
|
||||
"description": "Tunnel Rush is a fast-paced endless runner game where you navigate through a colorful tunnel filled with obstacles. How far can you go?",
|
||||
|
|
@ -451,6 +451,12 @@
|
|||
"slug": "tunnelrush",
|
||||
"unity": true
|
||||
},
|
||||
"ul6": {
|
||||
"name": "Ultima 6",
|
||||
"description": "Ultima 6 is a classic role-playing game that takes you on an epic adventure in a fantasy world. Explore, battle, and complete quests to save the realm.",
|
||||
"image": "/games/ul6/logo.png",
|
||||
"slug": "ul6"
|
||||
},
|
||||
"unfairmario": {
|
||||
"name": "Unfair Mario",
|
||||
"description": "Unfair Mario is a platformer game that challenges your skills and patience. Expect the unexpected as you navigate through tricky levels filled with hidden traps.",
|
||||
|
|
@ -458,12 +464,6 @@
|
|||
"slug": "unfairmario",
|
||||
"flash": true
|
||||
},
|
||||
"ul6": {
|
||||
"name": "Ultima 6",
|
||||
"description": "Ultima 6 is a classic role-playing game that takes you on an epic adventure in a fantasy world. Explore, battle, and complete quests to save the realm.",
|
||||
"image": "/games/ul6/logo.png",
|
||||
"slug": "ul6"
|
||||
},
|
||||
"vex3": {
|
||||
"name": "Vex 3",
|
||||
"description": "Vex 3 is a challenging platformer game where you navigate through various levels filled with obstacles and traps. Can you complete all the levels?",
|
||||
|
|
|
|||
|
|
@ -162,7 +162,6 @@ const DESCRIPTION =
|
|||
}
|
||||
|
||||
body {
|
||||
/* background-color: var(--background-color); */
|
||||
max-width: 100vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -174,9 +173,9 @@ const DESCRIPTION =
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
// button, input {
|
||||
// font-family: "Varela Round", sans-serif;
|
||||
// }
|
||||
button, input {
|
||||
font-family: "Varela Round", sans-serif;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 90%;
|
||||
|
|
|
|||
|
|
@ -21,22 +21,28 @@ export function getStaticPaths() {
|
|||
<Input inputName="games-search" placeholder={t("games.search")} height="30px" />
|
||||
</div>
|
||||
<div class="no-results"></div>
|
||||
<main id="main-content" class="grid">
|
||||
{
|
||||
Object.keys(games).map((key) => {
|
||||
const game = (games as any)[key];
|
||||
return <GameItem game={game} />;
|
||||
})
|
||||
}
|
||||
<main id="main-content">
|
||||
<div class="pinned-games grid"></div>
|
||||
<div class="all-games grid">
|
||||
{
|
||||
Object.keys(games).map((key) => {
|
||||
const game = (games as any)[key];
|
||||
return <GameItem game={game} />;
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<button id="reset-pinned">Reset Pinned Games</button>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<script>
|
||||
const search = document.getElementById("games-search-input") as HTMLInputElement;
|
||||
const mainContent = document.getElementById("main-content") as HTMLDivElement;
|
||||
const allGames = document.getElementsByClassName("all-games")[0] as HTMLDivElement;
|
||||
const pinnedGames = document.getElementsByClassName("pinned-games")[0] as HTMLDivElement;
|
||||
|
||||
search.addEventListener("input", () => {
|
||||
const filter = search.value.toUpperCase();
|
||||
const games = mainContent.children;
|
||||
const games = allGames.children;
|
||||
let results = 0;
|
||||
for (let i = 0; i < games.length; i++) {
|
||||
const game = games[i] as HTMLDivElement;
|
||||
|
|
@ -48,19 +54,82 @@ export function getStaticPaths() {
|
|||
game.style.display = "none";
|
||||
}
|
||||
}
|
||||
const noResults = document.querySelector(".no-results") as HTMLDivElement;
|
||||
if (results === 0) {
|
||||
const noResults = document.querySelector(".no-results") as HTMLDivElement;
|
||||
if (noResults) {
|
||||
noResults.style.display = "block";
|
||||
noResults.innerHTML = "No results found";
|
||||
}
|
||||
} else {
|
||||
const noResults = document.querySelector(".no-results") as HTMLDivElement;
|
||||
if (noResults) {
|
||||
noResults.style.display = "none";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const pins = document.querySelectorAll(".pin-icon");
|
||||
const localStoragePins = localStorage.getItem("alu__savedPins") || "[]"
|
||||
const savedPins = JSON.parse(localStoragePins);
|
||||
|
||||
pins.forEach((pin) => {
|
||||
const game = pin.parentElement as HTMLDivElement;
|
||||
const gameName = game.getAttribute("data-id")!;
|
||||
const isPinned = savedPins.includes(gameName);
|
||||
|
||||
if (isPinned) {
|
||||
game.classList.add("pinned");
|
||||
pin.setAttribute("src", "/img/games/pin.svg");
|
||||
pinnedGames.appendChild(game);
|
||||
if (allGames.contains(game)) {
|
||||
allGames.removeChild(game);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
pin.addEventListener("click", () => {
|
||||
const game = pin.parentElement as HTMLDivElement;
|
||||
const gameName = game.getAttribute("data-id")!;
|
||||
const isPinned = game.classList.contains("pinned");
|
||||
if (isPinned) {
|
||||
game.classList.remove("pinned");
|
||||
savedPins.splice(savedPins.indexOf(gameName), 1);
|
||||
localStorage.setItem("alu__savedPins", JSON.stringify(savedPins));
|
||||
pin.setAttribute("src", "/img/games/pin-outline.svg");
|
||||
allGames.prepend(game);
|
||||
if (pinnedGames.contains(game)) {
|
||||
pinnedGames.removeChild(game);
|
||||
}
|
||||
// Sort all games alphabetically again
|
||||
const allGamesArray = Array.from(allGames.children);
|
||||
allGamesArray.sort((a, b) => {
|
||||
const aName = a.getAttribute("data-id")!;
|
||||
const bName = b.getAttribute("data-id")!;
|
||||
return aName.localeCompare(bName);
|
||||
});
|
||||
allGamesArray.forEach((game) => {
|
||||
allGames.appendChild(game);
|
||||
});
|
||||
} else {
|
||||
game.classList.add("pinned");
|
||||
savedPins.push(gameName);
|
||||
localStorage.setItem("alu__savedPins", JSON.stringify(savedPins));
|
||||
pin.setAttribute("src", "/img/games/pin.svg");
|
||||
pinnedGames.appendChild(game);
|
||||
if (allGames.contains(game)) {
|
||||
allGames.removeChild(game);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const resetPinned = document.getElementById("reset-pinned") as HTMLButtonElement;
|
||||
|
||||
resetPinned.addEventListener("click", () => {
|
||||
localStorage.setItem("alu__savedPins", "[]");
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
@ -79,7 +148,7 @@ export function getStaticPaths() {
|
|||
text-align: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
width: 90%;
|
||||
width: 85%;
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
|
@ -92,4 +161,16 @@ export function getStaticPaths() {
|
|||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#reset-pinned {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
background-color: var(--accent-color-brighter);
|
||||
color: var(--text-color);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue