Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
# WEB102 Prework - *Name of App Here*
# WEB102 Prework - Sea Monster Crowdfunding

Submitted by: **Your Name Here**
Submitted by: **Olga Sherman**

**Name of your app** is a website for the company Sea Monster Crowdfunding that displays information about the games they have funded.
**Sea Monster Games Funding** is a website for the company Sea Monster Crowdfunding that displays information about the games they have funded.

Time spent: **X** hours spent in total
Time spent: **~25 hours** spent in total

## Required Features

The following **required** functionality is completed:

* [ ] The introduction section explains the background of the company and how many games remain unfunded.
* [ ] The Stats section includes information about the total contributions and dollars raised as well as the top two most funded games.
* [ ] The Our Games section initially displays all games funded by Sea Monster Crowdfunding
* [ ] The Our Games section has three buttons that allow the user to display only unfunded games, only funded games, or all games.
* [x] The introduction section explains the background of the company and how many games remain unfunded.
* [x] The Stats section includes information about the total contributions and dollars raised as well as the top two most funded games.
* [x] The Our Games section initially displays all games funded by Sea Monster Crowdfunding
* [x] The Our Games section has three buttons that allow the user to display only unfunded games, only funded games, or all games.
* [x] Top 2 games are displayed using destructuring and spread
* [x] Responsive layout using Flexbox

The following **optional** features are implemented:

* [ ] List anything else that you can get done to improve the app functionality!
* [x] Games that are not funded have a red border
* [x] Games that are funded have a green border
* [x] Live search box filters games by name
* [x] Background changed from grey to light yellow, header to cyan, added footer
* [x] Total money raised displayed in red
* [x] Buttons look moving up and down when hover over and clicked

## Video Walkthrough

## Video Walkthrough
Here's a walkthrough of implemented features:

<img src='http://i.imgur.com/link/to/your/gif/file.gif' title='Video Walkthrough' width='' alt='Video Walkthrough' />
<img src='walkthrough.gif' title='Video Walkthrough' width='600' alt='Video Walkthrough' />

<!-- Replace this with whatever GIF tool you used! -->
GIF created with ...
<!-- Recommended tools:
[Kap](https://getkap.co/) for macOS
[ScreenToGif](https://www.screentogif.com/) for Windows
[peek](https://github.com/phw/peek) for Linux. -->
GIF created with **LiceCap**

## Notes

Describe any challenges encountered while building the app.

- Took me some time to get up to speed with git
- I had to learn and debug how Flexbox css layouts worked
- Understanding reduce method, filter, destructuring, spread, arrow and other JS functions took a lot of time and practice
- At first, I forgot to use a local server, which caused CORS errors with module imports
- In Challenge #3 took me a while to figure out that tricky question where I learned that template literals require backticks ` `, not quotes
- Learned to do LICEcap, practiced a lot recording to keep time at minimum and demo key features

## License

Copyright [yyyy] [name of copyright owner]
Copyright Olga Sherman & CodePath 2025

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
13 changes: 12 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1 class="header-text">Sea Monster Crowdfunding</h1>
</div>

<!-- background info about company -->
<h2>Welcome to Sea Monster!</h2>
<h2>Welcome to Sea Monster Games Funding!</h2>
<div id="description-container">
<p>The purpose of our company is to fund independent games. We've been in operation for 12 years.</p>
</div>
Expand Down Expand Up @@ -50,13 +50,24 @@ <h3>🥈 Runner Up</h3>
<!-- list of games funded by Sea Monster -->
<h2>Our Games</h2>
<p>Check out each of our games below!</p>

<div id="search-container" style="text-align: center; margin: 20px;">
<input type="text" id="search-input" placeholder="Search games..." style="padding: 10px; width: 200px; border-radius: 7px;">
</div>

<div id="button-container">
<button id="unfunded-btn">Show Unfunded Only</button>
<button id="funded-btn">Show Funded Only</button>
<button id="all-btn">Show All Games</button>
</div>
<div id="games-container">

</div>
<p/><p/>
<!-- header row with logo -->
<div class="footer">
&copy Olga Sherman & CodePath 2025

</div>

<script type="module" src="index.js"></script>
Expand Down
124 changes: 100 additions & 24 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,46 @@ const gamesContainer = document.getElementById("games-container");
function addGamesToPage(games) {

// loop over each item in the data


for (let game of games) {
// create a new div element, which will become the game card


// add the class game-card to the list


// set the inner HTML using a template literal to display some info
const gameCard = document.createElement("div");
// add the class game-card to the list
gameCard.classList.add("game-card");
// set the inner HTML using a template literal to display some info
// about each game
// TIP: if your images are not displaying, make sure there is space
// between the end of the src attribute and the end of the tag ("/>")
gameCard.innerHTML = `
<img class="game-img" src="${game.img}" alt="${game.name}"/>
<h3 class="game-name">${game.name}</h3>
<p class="game-description">${game.description}</p>
<p><strong>Backers:</strong> ${game.backers}</p>
<p><strong>Pledged:</strong> $${game.pledged.toLocaleString()}</p>
`;

// ✅ Add red border to unfunded games
if (game.pledged < game.goal) {
gameCard.style.border = "4px solid red";
}

// Add green border to funded games
if (game.pledged >= game.goal) {
gameCard.style.border = "4px solid green";
}


// append the game to the games-container
// append the game to the games-container
gamesContainer.appendChild (gameCard);


}


}

// call the function we just defined using the correct variable
// later, we'll call this function using a different list of games
addGamesToPage([...GAMES_JSON].sort ((a, b) => b.pledged - a.pledged));


/*************************************************************************************
Expand All @@ -61,19 +81,31 @@ function addGamesToPage(games) {
const contributionsCard = document.getElementById("num-contributions");

// use reduce() to count the number of total contributions by summing the backers

const totalContributions = GAMES_JSON.reduce((acc, game) => acc + game.backers, 0);

// set the inner HTML using a template literal and toLocaleString to get a number with commas


contributionsCard.innerHTML = `
<p>${totalContributions.toLocaleString()}</p>
<p>Contributions</p>
`;
// grab the amount raised card, then use reduce() to find the total amount raised
const raisedCard = document.getElementById("total-raised");

const totalMoneyRaised = GAMES_JSON.reduce((acc, game) => acc + game.pledged, 0);
// set inner HTML using template literal

raisedCard.innerHTML = `
<p>$${totalMoneyRaised.toLocaleString()}</p>
<p>Amount Raised</p>
`;

// grab number of games card and set its inner HTML
const gamesCard = document.getElementById("num-games");
// grab the number of games card and use reduce() to count the number of games
const totalGames = GAMES_JSON.reduce((acc, game) => acc + 1, 0);
// set the inner HTML using template literal
gamesCard.innerHTML = `
<p>${totalGames.toLocaleString()}</p>
<p>Games</p>
`;


/*************************************************************************************
Expand All @@ -87,35 +119,45 @@ function filterUnfundedOnly() {
deleteChildElements(gamesContainer);

// use filter() to get a list of games that have not yet met their goal


const unfundedGames = GAMES_JSON.filter(game => game.pledged < game.goal);
console.log ('unfunded games = ',unfundedGames);

// use the function we previously created to add the unfunded games to the DOM

addGamesToPage (unfundedGames);
}

// show only games that are fully funded
function filterFundedOnly() {
deleteChildElements(gamesContainer);

// use filter() to get a list of games that have met or exceeded their goal

const fundedGames = GAMES_JSON.filter(game => game.pledged >= game.goal);
console.log ('funded games = ',fundedGames);

// use the function we previously created to add unfunded games to the DOM

addGamesToPage (fundedGames);
}

// show all games
function showAllGames() {
deleteChildElements(gamesContainer);

// add all games from the JSON data to the DOM
addGamesToPage(GAMES_JSON);
console.log ('all games = ',GAMES_JSON);

}

// select each button in the "Our Games" section
const unfundedBtn = document.getElementById("unfunded-btn");
unfundedBtn.addEventListener("click", filterUnfundedOnly);

const fundedBtn = document.getElementById("funded-btn");
fundedBtn.addEventListener("click", filterFundedOnly);

const allBtn = document.getElementById("all-btn");
allBtn.addEventListener("click", showAllGames);


// add event listeners with the correct functions to each button

Expand All @@ -129,10 +171,22 @@ const allBtn = document.getElementById("all-btn");
const descriptionContainer = document.getElementById("description-container");

// use filter or reduce to count the number of unfunded games
const unfundedGames = GAMES_JSON.filter(game => game.pledged < game.goal);
const numUnfundedGames = unfundedGames.length;


// create a string that explains the number of unfunded games using the ternary operator

const unfundedString = `There are ${numUnfundedGames} unfunded games.`;
// create a string that explains the number of funded games using the ternary operator
const fundedGames = GAMES_JSON.filter(game => game.pledged >= game.goal);
const numFundedGames = fundedGames.length;
const totalPledged = fundedGames.reduce((acc, game) => acc + game.pledged, 0);
const remainingText = numUnfundedGames === 1 ? "1 game remains" : `${numUnfundedGames} games remain`;
const displayStr = `A total of <span style="color: #CB0404"> $${totalPledged.toLocaleString()} </span> has been raised for ${numFundedGames} games. Currently, ${remainingText} unfunded. We need your help to fund these amazing games!`;
console.log(displayStr);
const descriptionParagraph = document.createElement("p");
descriptionParagraph.innerHTML = displayStr;
descriptionContainer.appendChild(descriptionParagraph);

// create a new DOM element containing the template string and append it to the description container

Expand All @@ -144,12 +198,34 @@ const descriptionContainer = document.getElementById("description-container");
const firstGameContainer = document.getElementById("first-game");
const secondGameContainer = document.getElementById("second-game");

const sortedGames = GAMES_JSON.sort( (item1, item2) => {
return item2.pledged - item1.pledged;
});
const sortedGames = [...GAMES_JSON].sort( (item1, item2) => item2.pledged - item1.pledged);


// use destructuring and the spread operator to grab the first and second games
const [firstGame, secondGame, ...others] = sortedGames;

console.log("Top Game:", firstGame.name);
console.log("Runner-up:", secondGame.name);

// create a new element to hold the name of the top pledge game, then append it to the correct element
const firstGameName = document.createElement("p");
firstGameName.textContent = firstGame.name;
firstGameContainer.appendChild(firstGameName);

// do the same for the runner up item
const secondGameName = document.createElement("p");
secondGameName.textContent = secondGame.name;
secondGameContainer.appendChild(secondGameName);

const searchInput = document.getElementById("search-input");

searchInput.addEventListener("input", (event) => {
const searchTerm = event.target.value.toLowerCase();

const filteredGames = GAMES_JSON.filter(game =>
game.name.toLowerCase().includes(searchTerm)
);

// do the same for the runner up item
deleteChildElements(gamesContainer);
addGamesToPage(filteredGames);
});
42 changes: 36 additions & 6 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

body {
font-family: 'Cabin';
background-color: #758190;
background-color: #FFFBDE; /*#758190 is a grayish color*/
}

#tentacles {
Expand All @@ -11,7 +11,7 @@ body {

.header {
display: flex;
background-color: lightblue;
background-color: #90D1CA;
padding: 1%;
align-items: center;
margin-left: -10px;
Expand All @@ -21,8 +21,14 @@ body {

.stats-container {
display: flex;
align-items: center; /* centers items vertically within the row */
}

.stats-container:hover {
cursor: pointer;
box-shadow: 0 0 40px #096B68;
}

.stats-card {
background-color: #a8b0bc;
border-radius: 7px;
Expand Down Expand Up @@ -59,7 +65,7 @@ body {

.game-card:hover {
cursor: pointer;
box-shadow: 0 0 30px lightblue;
box-shadow: 0 0 40px #096B68;
}

#button-container {
Expand All @@ -69,7 +75,31 @@ body {
button {
font-family: 'Cabin';
border: none;
padding: 1%;
margin: 1%;
padding: 10px 20px;
margin: 10px;
border-radius: 7px;
}
background-color: #096B68;
color: white;
font-weight: bold;
transition: all 0.1s ease-in-out;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
}

button:hover {
background-color: #129990;
cursor: pointer;
}

button:active {
transform: translateY(2px);
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
}

.footer {
background-color: #90D1CA;
color: black;
text-align: center;
padding: 20px;
margin-top: 40px;
font-size: 0.9em;
}
Binary file added walkthrough.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.