diff --git a/README.md b/README.md index a12177342..b49146b84 100644 --- a/README.md +++ b/README.md @@ -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: -Video Walkthrough +Video Walkthrough - -GIF created with ... - +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. diff --git a/index.html b/index.html index ba8123340..b385c11b0 100644 --- a/index.html +++ b/index.html @@ -14,7 +14,7 @@

Sea Monster Crowdfunding

-

Welcome to Sea Monster!

+

Welcome to Sea Monster Games Funding!

The purpose of our company is to fund independent games. We've been in operation for 12 years.

@@ -50,6 +50,11 @@

🥈 Runner Up

Our Games

Check out each of our games below!

+ +
+ +
+
@@ -57,6 +62,12 @@

Our Games

+
+

+ +

diff --git a/index.js b/index.js index 86fe7d438..34f91fc31 100644 --- a/index.js +++ b/index.js @@ -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 = ` + ${game.name} +

${game.name}

+

${game.description}

+

Backers: ${game.backers}

+

Pledged: $${game.pledged.toLocaleString()}

+ `; + + // ✅ 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)); /************************************************************************************* @@ -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 = ` +

${totalContributions.toLocaleString()}

+

Contributions

+`; // 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 = ` +

$${totalMoneyRaised.toLocaleString()}

+

Amount Raised

+`; // 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 = ` +

${totalGames.toLocaleString()}

+

Games

+`; /************************************************************************************* @@ -87,10 +119,11 @@ 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 @@ -98,10 +131,11 @@ 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 @@ -109,13 +143,21 @@ 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 @@ -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 $${totalPledged.toLocaleString()} 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 @@ -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 \ No newline at end of file + deleteChildElements(gamesContainer); + addGamesToPage(filteredGames); +}); \ No newline at end of file diff --git a/style.css b/style.css index 11303c2a7..aac6930cb 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ body { font-family: 'Cabin'; - background-color: #758190; + background-color: #FFFBDE; /*#758190 is a grayish color*/ } #tentacles { @@ -11,7 +11,7 @@ body { .header { display: flex; - background-color: lightblue; + background-color: #90D1CA; padding: 1%; align-items: center; margin-left: -10px; @@ -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; @@ -59,7 +65,7 @@ body { .game-card:hover { cursor: pointer; - box-shadow: 0 0 30px lightblue; + box-shadow: 0 0 40px #096B68; } #button-container { @@ -69,7 +75,31 @@ body { button { font-family: 'Cabin'; border: none; - padding: 1%; - margin: 1%; + padding: 10px 20px; + margin: 10px; border-radius: 7px; -} \ No newline at end of file + 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; + } \ No newline at end of file diff --git a/walkthrough.gif b/walkthrough.gif new file mode 100644 index 000000000..b982d1a13 Binary files /dev/null and b/walkthrough.gif differ