diff --git a/.gitignore b/.gitignore index 50d77de72..2bd84373f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ node_modules/ .env +.env.local +.vercel/ .DS_Store .vscode/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..3994ea9fe --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "sqltools.connections": [ + { + "previewLimit": 50, + "driver": "SQLite", + "name": "db sql", + "database": "db.sql" + } + ], + "cSpell.words": ["apod", "Desta", "Galactica"] +} diff --git a/courses/backend/advanced-javascript/README.md b/assets/courses/backend/advanced-javascript/README.md similarity index 100% rename from courses/backend/advanced-javascript/README.md rename to assets/courses/backend/advanced-javascript/README.md diff --git a/courses/backend/advanced-team-processes/README.md b/assets/courses/backend/advanced-team-processes/README.md similarity index 100% rename from courses/backend/advanced-team-processes/README.md rename to assets/courses/backend/advanced-team-processes/README.md diff --git a/courses/backend/collaboration-via-github/README.md b/assets/courses/backend/collaboration-via-github/README.md similarity index 100% rename from courses/backend/collaboration-via-github/README.md rename to assets/courses/backend/collaboration-via-github/README.md diff --git a/courses/backend/databases/README.md b/assets/courses/backend/databases/README.md similarity index 100% rename from courses/backend/databases/README.md rename to assets/courses/backend/databases/README.md diff --git a/courses/backend/databases/database/tasks-postgres.sql b/assets/courses/backend/databases/database/tasks-postgres.sql similarity index 100% rename from courses/backend/databases/database/tasks-postgres.sql rename to assets/courses/backend/databases/database/tasks-postgres.sql diff --git a/courses/backend/databases/database/tasks-sample-data.sql b/assets/courses/backend/databases/database/tasks-sample-data.sql similarity index 100% rename from courses/backend/databases/database/tasks-sample-data.sql rename to assets/courses/backend/databases/database/tasks-sample-data.sql diff --git a/courses/backend/databases/example-api/.env.example b/assets/courses/backend/databases/example-api/.env.example similarity index 100% rename from courses/backend/databases/example-api/.env.example rename to assets/courses/backend/databases/example-api/.env.example diff --git a/courses/backend/databases/example-api/index.js b/assets/courses/backend/databases/example-api/index.js similarity index 100% rename from courses/backend/databases/example-api/index.js rename to assets/courses/backend/databases/example-api/index.js diff --git a/courses/backend/databases/example-api/package-lock.json b/assets/courses/backend/databases/example-api/package-lock.json similarity index 100% rename from courses/backend/databases/example-api/package-lock.json rename to assets/courses/backend/databases/example-api/package-lock.json diff --git a/courses/backend/databases/example-api/package.json b/assets/courses/backend/databases/example-api/package.json similarity index 100% rename from courses/backend/databases/example-api/package.json rename to assets/courses/backend/databases/example-api/package.json diff --git a/courses/backend/node/README.md b/assets/courses/backend/node/README.md similarity index 100% rename from courses/backend/node/README.md rename to assets/courses/backend/node/README.md diff --git a/courses/backend/using-ai-in-development/README.md b/assets/courses/backend/using-ai-in-development/README.md similarity index 100% rename from courses/backend/using-ai-in-development/README.md rename to assets/courses/backend/using-ai-in-development/README.md diff --git a/assets/courses/foundation/Intro-to-agile/Trello.txt b/assets/courses/foundation/Intro-to-agile/Trello.txt new file mode 100644 index 000000000..c097ed692 --- /dev/null +++ b/assets/courses/foundation/Intro-to-agile/Trello.txt @@ -0,0 +1,2 @@ + +https://trello.com/b/opBYR6Ge/bake-birthday-cake \ No newline at end of file diff --git a/courses/foundation/databases/README.md b/assets/courses/foundation/databases/README.md similarity index 100% rename from courses/foundation/databases/README.md rename to assets/courses/foundation/databases/README.md diff --git a/assets/courses/foundation/databases/db.sql b/assets/courses/foundation/databases/db.sql new file mode 100644 index 000000000..a34ee37cb --- /dev/null +++ b/assets/courses/foundation/databases/db.sql @@ -0,0 +1,30 @@ +--1 How many tasks are in the task table? +SELECT COUNT(*) FROM task; + +--2 How many tasks in the task table do not have a valid due date? + SELECT COUNT(*) AS invalid_due_dates FROM task WHERE due_date IS NULL; + +--3 Find all the tasks that are marked as done. + SELECT * FROM task WHERE status_id = 3; + +--4 Find all the tasks that are not marked as done. +SELECT * FROM task WHERE status_id != 3; + +--5 Get all the tasks, sorted with the most recently created first. +SELECT * FROM task ORDER BY created DESC; + +--6 Get the single most recently created task. +SELECT * FROM task ORDER BY created DESC LIMIT 1; + +--7 Get the title and due date of all tasks where the title or description contains database. +SELECT title, due_date FROM task WHERE title LIKE '%database%' OR description LIKE '%database%'; + +--8 Get the title and status (as text) of all tasks. +SELECT t.title, s.name FROM task t LEFT JOIN status s ON t.status_id = s.id; + +--9 Get the name of each status, along with a count of how many tasks have that status. +SELECT s.name AS status, COUNT(t.id) AS status_count FROM status s LEFT JOIN task t ON t.status_id = s.id GROUP BY s.id, s.name; + +--10 Get the names of all statuses, sorted by the status with most tasks first. +SELECT s.name, COUNT(*) AS status_count FROM task t JOIN status s ON t.status_id = s.id +GROUP BY s.name ORDER BY status_count DESC; \ No newline at end of file diff --git a/courses/foundation/git/README.md b/assets/courses/foundation/git/README.md similarity index 100% rename from courses/foundation/git/README.md rename to assets/courses/foundation/git/README.md diff --git a/assets/courses/foundation/git/week1/countries.txt b/assets/courses/foundation/git/week1/countries.txt new file mode 100644 index 000000000..45c0aeba5 --- /dev/null +++ b/assets/courses/foundation/git/week1/countries.txt @@ -0,0 +1,3 @@ +Ethiopia +USA +Sweden \ No newline at end of file diff --git a/assets/courses/foundation/git/week1/my-favourite-food.txt b/assets/courses/foundation/git/week1/my-favourite-food.txt new file mode 100644 index 000000000..e56a4c1c2 --- /dev/null +++ b/assets/courses/foundation/git/week1/my-favourite-food.txt @@ -0,0 +1,26 @@ +Fish Balls (Simple Home Recipe) + +Ingredients: +- 500 g white fish fillets (cod, pollock or haddock), skin removed +- 1 egg, lightly beaten +- 2 spring onions, finely chopped +- 2 cloves garlic, minced +- 1 teaspoon soy sauce +- 1 teaspoon sesame oil +- 1/2 teaspoon salt (adjust to taste) +- 1/4 teaspoon white or black pepper +- 3 tablespoons cornstarch (plus extra for dusting) +- Vegetable oil, for frying or cooking + +Instructions: +1. Chop the fish into small pieces and place into a large bowl or food processor. +2. Add the egg, spring onions, garlic, soy sauce, sesame oil, salt and pepper. +3. Pulse or mix until you get a smooth, sticky paste. If too loose, add 1 tablespoon cornstarch at a time until the mixture holds together. +4. Wet your hands and shape the mixture into small balls (about 1" / 2–3 cm diameter). +5. Option A — Boil: Bring a pot of water to a gentle boil and drop the fish balls in. Cook until they float (3–5 minutes). Remove with a slotted spoon. + Option B — Pan-fry: Heat 2–3 tablespoons vegetable oil in a skillet and shallow-fry the fish balls, turning occasionally, until golden and cooked through (about 6–8 minutes). +6. Serve hot with dipping sauce, in noodle soup, or as a snack. + +Tips: +- For a springier texture, chill the fish paste for 30 minutes before shaping. +- You can substitute a mixture of fish and shrimp for a different flavor. \ No newline at end of file diff --git a/assets/courses/foundation/git/week1/my-second-favorite-food.txt b/assets/courses/foundation/git/week1/my-second-favorite-food.txt new file mode 100644 index 000000000..925ae38b2 --- /dev/null +++ b/assets/courses/foundation/git/week1/my-second-favorite-food.txt @@ -0,0 +1,27 @@ +Vegetable Stir-Fry with Garlic Sauce + +Ingredients: +- 3 cups mixed vegetables (broccoli florets, bell peppers, carrots, snap peas) +- 200 g firm tofu or sliced mushrooms (optional) +- 3 cloves garlic, minced +- 1 tbsp fresh ginger, minced +- 2 tbsp soy sauce +- 1 tbsp oyster sauce (or vegetarian alternative) +- 1 tsp sugar +- 1 tbsp sesame oil +- 2 tbsp vegetable oil for frying +- 1 tbsp cornstarch mixed with 3 tbsp water (slurry) + +Instructions: +1. Prepare all vegetables and proteins, cutting into bite-sized pieces. +2. Heat vegetable oil in a wok or large skillet over high heat. +3. Add garlic and ginger, stir-fry briefly until fragrant (20–30 seconds). +4. Add tofu or mushrooms, fry until lightly browned. +5. Add vegetables and stir-fry for 3–5 minutes until crisp-tender. +6. Mix soy sauce, oyster sauce, sugar and sesame oil; pour over the vegetables. +7. Add cornstarch slurry and stir until the sauce thickens and coats the vegetables. +8. Serve immediately over steamed rice or noodles. + +Variations: +- Add chili flakes or fresh chilies for heat. +- Swap tofu for chicken or shrimp for a non-vegetarian version. \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/.gitignore b/assets/courses/foundation/intro-to-backend/.gitignore similarity index 100% rename from courses/foundation/intro-to-backend/.gitignore rename to assets/courses/foundation/intro-to-backend/.gitignore diff --git a/courses/foundation/intro-to-backend/README.md b/assets/courses/foundation/intro-to-backend/README.md similarity index 100% rename from courses/foundation/intro-to-backend/README.md rename to assets/courses/foundation/intro-to-backend/README.md diff --git a/courses/foundation/intro-to-backend/database.sqlite3 b/assets/courses/foundation/intro-to-backend/database.sqlite3 similarity index 100% rename from courses/foundation/intro-to-backend/database.sqlite3 rename to assets/courses/foundation/intro-to-backend/database.sqlite3 diff --git a/courses/foundation/intro-to-backend/exercise1.js b/assets/courses/foundation/intro-to-backend/exercise1.js similarity index 100% rename from courses/foundation/intro-to-backend/exercise1.js rename to assets/courses/foundation/intro-to-backend/exercise1.js diff --git a/courses/foundation/intro-to-backend/exercise2.js b/assets/courses/foundation/intro-to-backend/exercise2.js similarity index 100% rename from courses/foundation/intro-to-backend/exercise2.js rename to assets/courses/foundation/intro-to-backend/exercise2.js diff --git a/courses/foundation/intro-to-backend/package-lock.json b/assets/courses/foundation/intro-to-backend/package-lock.json similarity index 100% rename from courses/foundation/intro-to-backend/package-lock.json rename to assets/courses/foundation/intro-to-backend/package-lock.json diff --git a/courses/foundation/intro-to-backend/package.json b/assets/courses/foundation/intro-to-backend/package.json similarity index 100% rename from courses/foundation/intro-to-backend/package.json rename to assets/courses/foundation/intro-to-backend/package.json diff --git a/assets/courses/foundation/intro-to-backend/tasks.sqlite3 b/assets/courses/foundation/intro-to-backend/tasks.sqlite3 new file mode 100644 index 000000000..34bfe1019 Binary files /dev/null and b/assets/courses/foundation/intro-to-backend/tasks.sqlite3 differ diff --git a/courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js b/assets/courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js similarity index 97% rename from courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js rename to assets/courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js index a981c968a..574a396fa 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js +++ b/assets/courses/foundation/intro-to-frontend/HYFBay/hyfBayHelpers.js @@ -57,7 +57,7 @@ window.getAvailableProducts = function () { const numberOfAvailableProducts = getRandomInt(0, 30); const availableProducts = Array.apply( null, - Array(numberOfAvailableProducts), + Array(numberOfAvailableProducts) ).map(() => { const name = getRandomProductName(); return { diff --git a/courses/foundation/intro-to-frontend/HYFBay/index.html b/assets/courses/foundation/intro-to-frontend/HYFBay/index.html similarity index 59% rename from courses/foundation/intro-to-frontend/HYFBay/index.html rename to assets/courses/foundation/intro-to-frontend/HYFBay/index.html index 07f60fe48..201308bc8 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/index.html +++ b/assets/courses/foundation/intro-to-frontend/HYFBay/index.html @@ -8,7 +8,16 @@ /> -
+
+
+

HYF-Bay🤑

+

Your Favorite Marketplace

+
+
+

Products

+ +
+
diff --git a/assets/courses/foundation/intro-to-frontend/HYFBay/main.css b/assets/courses/foundation/intro-to-frontend/HYFBay/main.css new file mode 100644 index 000000000..4bb3474c9 --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/HYFBay/main.css @@ -0,0 +1,31 @@ +body { + font-family: "Open Sans", sans-serif; + background-color: #f9fbfd; + padding: 20px; +} + +* { + box-sizing: border-box; +} + +body, +h1, +h2 { + margin: 0; + text-align: center; +} +.products-section { + max-width: 1200px; + margin: 0 auto; +} +.product-item { + display: flex; + flex-direction: column; + margin: 20px 0 10px 30px; + list-style-type: none; + background-color: lightyellow; + padding: 15px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, + 0, 0.1); +} diff --git a/assets/courses/foundation/intro-to-frontend/HYFBay/main.js b/assets/courses/foundation/intro-to-frontend/HYFBay/main.js new file mode 100644 index 000000000..5a0b4376e --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/HYFBay/main.js @@ -0,0 +1,22 @@ +console.log("Script loaded"); + +const products = getAvailableProducts(); +console.log(products); + +// This should create the ul and the li's with the individual products details + +function renderProducts(products) { + const productList = document.getElementById("product-list"); + + products.forEach((product) => { + const listItem = document.createElement("li"); + listItem.classList.add("product-item"); + listItem.innerHTML = `${product.name} + Price: $${product.price.toFixed(2)} +Rating: ${product.rating} / 10 + `; + productList.appendChild(listItem); + }); +} + +renderProducts(products); diff --git a/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/README.md b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/README.md similarity index 100% rename from courses/foundation/intro-to-frontend/HogwartsHouseGenerator/README.md rename to assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/README.md diff --git a/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/hogwarts.js b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/hogwarts.js new file mode 100644 index 000000000..e4fda8c96 --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/hogwarts.js @@ -0,0 +1,74 @@ +const houses = [ + { + name: "Gryffindor", + description: + "Gryffindor values courage, bravery, nerve and chivalry. Its mascot is the lion, and its colours are scarlet and gold. The Gryffindor motto is Their daring, nerve and chivalry set Gryffindors apart. The Head of this house is the Transfiguration teacher and Deputy Headmistress, Minerva McGonagall, and the house ghost is Sir Nicholas de Mimsy-Porpington, more commonly known as Nearly Headless Nick. According to Rowling, Gryffindor corresponds roughly to the element of fire. The founder of the house is Godric Gryffindhighest towers, the entrance to which is located on the seventh floor in the east wing of the castle and is guarded by a painting of The Fat Lady, who is garbed in a pink dress. She permits entry only after being given the correct password, as was distinguished in the third book, when Sirius Black tried forcing entry into the tower, only to be blocked by The Fat Lady after he could not give the correct password. In the first book, Neville Longbottom tends to forget the password and must wait near the painting until other Gryffindors arrive to open the way.", + image: + "https://harrypottercrazies.weebly.com/uploads/1/8/4/4/18445957/4778832.jpg", + }, + { + name: "Hufflepuff", + description: + "Hufflepuff house values hard work, patience, justice, and loyalty. The house mascot is the badger, and the house colours are yellow and black. The Hufflepuff motto is Those patient Hufflepuffs are true and unafraid of toil. The head of this house is the Herbology professor, Pomona Sprout, and the house ghost is the Fat Friar. According to Rowling, Hufflepuff corresponds roughly to the element of earth. The founder of this house is Helga Hufflepuff. The Hufflepuff dormitories and common room are located near the castle kitchens, in a cozy nook that can be reached through a stack of large barrels in a nook near the kitchens. The entrance is concealed by a large barrel; to gain entry, one must tap the barrel in a certain rhythm (which changes from time to time) to open it up. The common room is a vast underground cavern with earthy tones, low ceilings, and numerous plants and fungi growing from the walls. There are many cozy chairs and sofas around small fireplaces, as well as low tables for studying and socializing.", + image: + "https://harrypottercrazies.weebly.com/uploads/1/8/4/4/18445957/3077859.jpg?303", + }, + { + name: "Ravenclaw", + description: + 'Ravenclaw values intelligence, creativity, learning, and wit. The house mascot is an eagle and the house colours are blue and bronze blue and grey in the films. The Ravenclaw motto is "Wit beyond measure is man\'s greatest treasure." The head of this house is the Charms professor, Filius Flitwick, and the house ghost is The Grey Lady. According to Rowling, Ravenclaw corresponds roughly to the element of air. The founder of this house is Rowena Ravenclaw. The dormitories are located in Ravenclaw Tower, on the west side of Hogwarts. The common room, which went undescribed in the series until the climax of Deathly Hallows, is round and filled with blue hangings and armchairs, has a domed ceiling painted with stars and features a replica statue of Rowena wearing her diadem. Harry also notes that Ravenclaws "have a spectacular view of the surrounding mountains"', + image: + "https://harrypottercrazies.weebly.com/uploads/1/8/4/4/18445957/1177755.jpg?264", + }, + { + name: "Slytherin", + description: + "Slytherin house values ambition, cunning, leadership, and resourcefulness; the Sorting Hat said in Harry Potter and the Philosopher's Stone that Slytherins will do anything to get their way. The house mascot of Slytherin is the serpent, and the house colours are green and silver. The Slytherin motto is Slytherin will help you on your way to greatness. Salazar Slytherin founded the house. The Head of House is Severus Snape until near the end of the sixth book. Then, Horace Slughorn, the previous Head of House, comes out of retirement re-assuming authority. The ghost of Slytherin house is The Bloody Baron. According to Rowling, Slytherin corresponds roughly to the element of water. The Slytherin dormitories and common room are reached through a bare stone wall in the dungeons. The Slytherin common room is a long, low, dungeon-style room, located under the Hogwarts Lake, furnished with green lamps and carved armchairs. The room is described in the second book as having a greenish glow.", + image: + "https://harrypottercrazies.weebly.com/uploads/1/8/4/4/18445957/987119.jpg?250", + }, +]; + +const usernameInput = document.getElementById("username"); +const getHouseBtn = document.getElementById("getHouseBtn"); +const retryBtn = document.getElementById("retryBtn"); +const houseResult = document.getElementById("houseResult"); +const houseName = document.getElementById("houseName"); +const houseDescription = document.getElementById("houseDescription"); +const houseImage = document.getElementById("houseImage"); + +let lastHouseIndex = -1; // Track the last selected house index + +function getRandomHouse() { + const username = usernameInput.value.trim(); + if (username === "") { + houseResult.textContent = "Please enter your name to get sorted!"; + houseResult.classList.remove("hidden"); + return; + } + + // Generate a new random index that is not the same as the last one + let randomIndex; + do { + randomIndex = Math.floor(Math.random() * houses.length); + } while (randomIndex === lastHouseIndex); + lastHouseIndex = randomIndex; // Update last index + + const house = houses[randomIndex]; + + houseName.textContent = `You belong in ${house.name}!`; + houseDescription.textContent = house.description; + houseImage.src = house.image; + + houseResult.textContent = `${username} belongs in ${house.name}!`; + houseResult.classList.remove("error", "hidden"); + + // Change button text after first click + if (getHouseBtn.textContent === "Get a House") { + getHouseBtn.textContent = "Assign New House"; + } + retryBtn.classList.remove("hidden"); +} + +getHouseBtn.addEventListener("click", getRandomHouse); +retryBtn.addEventListener("click", getRandomHouse); diff --git a/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html new file mode 100644 index 000000000..6e198039f --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html @@ -0,0 +1,38 @@ + + + + + + + Hogwarts House generator + + +
+

Hogwarts House generator

+ + + + + + + + +

+
+ house-image +

+
+
+ + + diff --git a/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css new file mode 100644 index 000000000..f95e627ac --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css @@ -0,0 +1,98 @@ +@import url("https://fonts.googleapis.com/css2?family=Bitter:ital,wght@0,100..900;1,100..900&family=Playwrite+US+Modern:wght@100..400&display=swap"); + +body { + font-family: Bitter; + background-color: #0e0e0e; + margin: 0 auto; + padding: 50px; + color: #fff; +} +h1 { + text-align: center; + color: #fff; +} +.container { + max-width: 800px; + margin: 0 auto; + background-color: #7f2c2c; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} +.input-text { + width: 50%; + height: auto; + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 1rem; +} + +#getHouseBtn { + background-color: #d3d35d; + padding: 10px 20px; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.3s ease; +} +#getHouseBtn:hover { + background-color: #b5b53f; + color: #fff; +} +#retryBtn { + background-color: #4fb2d3; + padding: 10px 20px; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.3s ease; +} +#retryBtn:hover { + background-color: #3f8fa9; + color:#fff; +} +.house-info { + display: flex; + align-items: center; + margin-top: 20px; + gap: 25px; +} +.house-img { + width: 200px; + height: auto; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); +} + +@media (max-width: 768px) { + body { + padding: 10px; + } + .container { + max-width: 100%; + padding: 15px; + } + .house-info { + flex-direction: column; + gap: 10px; + } + h1 { + font-size: 1.5rem; + } + .input-text { + width: 100%; + font-size: 1rem; + padding: 8px; + } + button { + width: 100%; + margin-top: 10px; + } +} + +.hidden { + display: none; +} diff --git a/courses/foundation/intro-to-frontend/README.md b/assets/courses/foundation/intro-to-frontend/README.md similarity index 100% rename from courses/foundation/intro-to-frontend/README.md rename to assets/courses/foundation/intro-to-frontend/README.md diff --git a/assets/courses/foundation/intro-to-frontend/codewar.txt b/assets/courses/foundation/intro-to-frontend/codewar.txt new file mode 100644 index 000000000..fb70cb136 --- /dev/null +++ b/assets/courses/foundation/intro-to-frontend/codewar.txt @@ -0,0 +1 @@ +Codewar https://www.codewars.com/users/Idesta1 \ No newline at end of file diff --git a/assets/courses/foundation/intro-to-javascript/README.md b/assets/courses/foundation/intro-to-javascript/README.md new file mode 100644 index 000000000..d42039874 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/README.md @@ -0,0 +1,18 @@ +🧠 JavaScript Basics — Week 1 @ Hack Your Future + +Welcome to my JavaScript Week 1 project! + +This assignment is part of my learning journey at Hack Your Future, where I’m exploring the foundations of programming with JavaScript — focusing on variables, arrays, and basic operations. + +🚀 About Smart-ease + +Smart-ease is a fictional startup tech company created for this assignment. + +Our mission is to solve small but smart problems with simple, effective JavaScript solutions. + +As part of our work, we completed a series of JavaScript tasks demonstrating core programming concepts. + +learned declaring and using variables +creating and manipulating arrays +performing mathematical operations +practice console.log and debugging diff --git a/assets/courses/foundation/intro-to-javascript/excercise/exc.js b/assets/courses/foundation/intro-to-javascript/excercise/exc.js new file mode 100644 index 000000000..78e2b9e54 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/excercise/exc.js @@ -0,0 +1,10 @@ +const input = ["God", "Wolf", "Rail", "Gum", "Maps", "Live"]; + +function reverseWords(words) { + const length = words.length; + let reverse = " "; + for (let i = words.length - 1; i >= 0; i--) {} + return reverse; +} + +console.log(reverseWords(input)); diff --git a/assets/courses/foundation/intro-to-javascript/excercise/pizza.js b/assets/courses/foundation/intro-to-javascript/excercise/pizza.js new file mode 100644 index 000000000..057eb167a --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/excercise/pizza.js @@ -0,0 +1,32 @@ +const favoritePizza = "margarita"; +let margaritaPrice = 100; +let pizzaCount = 5; +let takeAway = true; + +const totalPrice = margaritaPrice * pizzaCount; + +if (takeAway) { + console.log( + "New pizza order: TakeAway" + + " " + + pizzaCount + + " " + + favoritePizza + + "." + + " Total cost for your order is " + + totalPrice + + " Kroner." + ); +} else { + console.log( + "New pizza order: In store" + + " " + + pizzaCount + + " " + + favoritePizza + + "." + + "Total cost for your pizza is " + + totalPrice + + " Kroner." + ); +} diff --git a/assets/courses/foundation/intro-to-javascript/week1/agify.html b/assets/courses/foundation/intro-to-javascript/week1/agify.html new file mode 100644 index 000000000..b16b9c800 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week1/agify.html @@ -0,0 +1,204 @@ + + + + + + Agi-fy + + + +
+

Agi-fy(Future Age Calculator)

+
+
+
+ + + + +
+
+ + + + +
+ +
+
+

+ +
+ + + diff --git a/assets/courses/foundation/intro-to-javascript/week1/eznamey.js b/assets/courses/foundation/intro-to-javascript/week1/eznamey.js new file mode 100644 index 000000000..d8b554491 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week1/eznamey.js @@ -0,0 +1,32 @@ +let firstWords = [ + "meta", + "tech", + "awesome", + "Easy", + "solution", + "Happy", + "solve", + "world", + "Best", + "terminal", +]; +let secondWords = [ + "lab", + "bbq", + "geek", + "norse", + "buddy", + "dog", + "memo", + "star", + "space", + "c", +]; + +const randomNumber = Math.floor(Math.random() * 10); +const randomFirst = firstWords[Math.floor(Math.random() * 10)]; +const randomSecond = secondWords[Math.floor(Math.random() * 10)]; + +const startupName = `${randomFirst} ${randomSecond}`; + +console.log("Your startup name is:", startupName); diff --git a/assets/courses/foundation/intro-to-javascript/week1/goodboy.js b/assets/courses/foundation/intro-to-javascript/week1/goodboy.js new file mode 100644 index 000000000..42efe9e55 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week1/goodboy.js @@ -0,0 +1,13 @@ +const yearOfBirth = 2010; +const yearFuture = 2025; +const age = yearFuture - yearOfBirth; +const shouldShowResultInDogYears = true; +const dogYearsEquivalent = age * 7; + +if (shouldShowResultInDogYears) { + console.log( + "Your dog will be " + dogYearsEquivalent + " dog years old in " + yearFuture + ); +} else if (age) { + console.log("Your dog will be " + age + " human years old in " + yearFuture); +} diff --git a/assets/courses/foundation/intro-to-javascript/week1/housey.js b/assets/courses/foundation/intro-to-javascript/week1/housey.js new file mode 100644 index 000000000..a8cc66d93 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week1/housey.js @@ -0,0 +1,39 @@ +//peter's estimate + +const peterWidth = 8; +const peterDepth = 10; +const peterHeight = 10; + +const peterGardenSizeInM2 = 100; +const peterHouseCosts = 25000000; +const peterVolumeInMeters = peterWidth * peterDepth * peterHeight; +const peterHousePrice = + peterVolumeInMeters * 2.5 * 1000 + peterGardenSizeInM2 * 300; + +if (peterHouseCosts > peterHousePrice) { + console.log("You are paying more"); +} else if (peterHouseCosts < peterHousePrice) { + console.log("You are paying less"); +} else { + console.log("You are paying fair!"); +} + +//Julia's estimate + +const juliaWidth = 5; +const juliaDepth = 8; +const juliaHeight = 11; + +const juliaGardenSizeInM2 = 100; +const juliaHouseCosts = 2000000; +const juliaVolumeInMeters = juliaWidth * juliaDepth * juliaHeight; +const juliaHousePrice = + juliaVolumeInMeters * 2.5 * 1000 + juliaGardenSizeInM2 * 300; + +if (juliaHouseCosts > juliaHousePrice) { + console.log("You are paying more"); +} else if (juliaHouseCosts < juliaHousePrice) { + console.log("You are paying less"); +} else { + console.log("You have paid fair!"); +} diff --git a/assets/courses/foundation/intro-to-javascript/week2/candy.js b/assets/courses/foundation/intro-to-javascript/week2/candy.js new file mode 100644 index 000000000..66f18f62c --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/candy.js @@ -0,0 +1,31 @@ +const boughtCandyPrices = []; + +function addCandy(candyType, weight) { + let pricePerGram; + if (candyType === "sweet") { + pricePerGram = 0.5; + } else if (candyType === "chocolate") { + pricePerGram = 0.7; + } else if (candyType === "toffee") { + pricePerGram = 1.1; + } else if (candyType === "chewing-gum") { + pricePerGram = 0.03; + } else { + console.log("Unknown candy type"); + return; + } + + const totalPrice = pricePerGram * weight; + boughtCandyPrices.push(candyType, totalPrice.toFixed()); + return boughtCandyPrices; +} + +const amountToSpend = Math.random() * 100; +console.log(`You have ${amountToSpend.toFixed(2)} kroner to spend on candy.`); + +console.log(canBuyMoreCandy()); + +console.log(addCandy("sweet", 20)); +console.log(addCandy("chocolate", 15)); +console.log(addCandy("toffee", 10)); +console.log(addCandy("chewing-gum", 5)); diff --git a/assets/courses/foundation/intro-to-javascript/week2/event.js b/assets/courses/foundation/intro-to-javascript/week2/event.js new file mode 100644 index 000000000..626643881 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/event.js @@ -0,0 +1,24 @@ +function getEventWeekday(daysToAdd) { + const weekDays = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ]; + + const date = new Date(); + const WeekDay = date.getDay(); + const EventDay = (WeekDay + daysToAdd) % weekDays.length; + + return weekDays[EventDay]; +} + +console.log(getEventWeekday(7)); +console.log(getEventWeekday(1)); + +//function getEventWeekday with daysToAdd parameter, +// declared variable in array weekDays Sunday - Saturday, +// use new date() to access current date and getDay() to get current weekday 0-6, diff --git a/assets/courses/foundation/intro-to-javascript/week2/flight.js b/assets/courses/foundation/intro-to-javascript/week2/flight.js new file mode 100644 index 000000000..f3fbfed41 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/flight.js @@ -0,0 +1,28 @@ +//Flight booking fullname function +function getFullName(firstName, surName, useFormalName, gender) { + const formalName1 = "Lord"; + const formalName2 = "Madam"; + const fullName = firstName + " " + surName; + if (useFormalName === true && gender === "man") { + return formalName1 + " " + fullName; + } else if (useFormalName === true && gender === "woman") { + return formalName2 + " " + fullName; + } else { + return fullName; + } +} + +const fullName1 = "Sam"; +const fullName2 = "David"; + +console.log(getFullName("Benjamin", "Hughes", true, "man")); +console.log(getFullName("Sarah", "Johnson", false, "woman")); +console.log(getFullName("Dina", "Smith", true, "woman")); + +console.log(getFullName(fullName1, fullName2)); + +//Formal fullname +//to add formal name i added useFormalName another parameter and used if else condition and added boolean value to check if true to add formal name if false then just fullname. +// i declared two variables formalName1 and formalName2 to store "Lord" and "Madam". +//i called the function twice with different values to check if it works correctly. +// to add gender options i added another parameter gender and used if else condition with "man" and "woman". diff --git a/assets/courses/foundation/intro-to-javascript/week2/freecodecamp.txt b/assets/courses/foundation/intro-to-javascript/week2/freecodecamp.txt new file mode 100644 index 000000000..fe8786db7 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/freecodecamp.txt @@ -0,0 +1 @@ +https://www.freecodecamp.org/idesta \ No newline at end of file diff --git a/assets/courses/foundation/intro-to-javascript/week2/student.js b/assets/courses/foundation/intro-to-javascript/week2/student.js new file mode 100644 index 000000000..fab9e2368 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/student.js @@ -0,0 +1,49 @@ +const class07Students = ["Sam", "John", "Ben", "Rob", "Nancy", "Nova"]; +//total + +function addStudentToClass(studentName) { + // can not add empty string + if (!studentName) { + console.log("Cannot add empty string"); + return; + } + //student already exists + if (class07Students.includes(studentName)) { + console.log(`Student ${studentName} is already in the class`); + return; + } + // can not add more than 6 students + if (class07Students.length >= 6 && studentName !== "QueenMary") { + console.log("Cannot add more students to class 07"); + return; + } + //exceptional rule only for the Queen + if (studentName === "QueenMary") { + class07Students.push(studentName); + console.log("The Queen has to be added"); + return; + } +} + +//add student to class +addStudentToClass("Susan"); +addStudentToClass("Ben"); +addStudentToClass("QueenMary"); +addStudentToClass(""); + +// to add more students +function getNumberOfStudents(studentName) { + if (class07Students.push(studentName)) { + console.log(`Add ${studentName} to the class`); + return; + } +} +// get total of students +const total = class07Students.length; +console.log(total); +getNumberOfStudents("Jared"); +getNumberOfStudents("Lisa"); +getNumberOfStudents("Gelila"); +getNumberOfStudents("Sam"); +getNumberOfStudents("QueenMary"); +getNumberOfStudents(total); diff --git a/assets/courses/foundation/intro-to-javascript/week2/weatherwear.js b/assets/courses/foundation/intro-to-javascript/week2/weatherwear.js new file mode 100644 index 000000000..8cb974cf7 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week2/weatherwear.js @@ -0,0 +1,19 @@ +function whatToWear(temperature) { + const winter = `Jacket , pants and sweater`; + const summer = `t-shirt , shorts and summer-dress`; //using template literals + + if (temperature >= 17) { + return `You can wear ${summer}`; + } else if (temperature < 17) { + return `You can wear ${winter}`; + } else { + return "You can always decide what to wear"; + } +} + +console.log(whatToWear(20)); +console.log(whatToWear(10)); +console.log(whatToWear()); + +//added temperature parameter and used if else condition to return whatToWear, +//used template literal to concatenating strings diff --git a/assets/courses/foundation/intro-to-javascript/week3/array.js b/assets/courses/foundation/intro-to-javascript/week3/array.js new file mode 100644 index 000000000..876686af1 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week3/array.js @@ -0,0 +1,92 @@ +// Item array removal... +const names = [ + "Peter", + "Ahmad", + "Yana", + "kristina", + "Rasmus", + "Samuel", + "Katrine", + "Tala", +]; + +const namesToRemove = "Ahmed"; +const index = names.indexOf(namesToRemove); + +if (index !== -1) { + names.splice(index, 1); +} +console.log(names.splice(1, 1)); +console.log(names); // ['Peter', 'Yana', 'kristina', 'Rasmus', 'Samuel', 'Katrine', 'Tala'] + +//When will we be there?? +const travelInformation = { + speed: 50, + destinationDistance: 432, +}; +const distance = travelInformation.destinationDistance; +const speed = travelInformation.speed; +const travelTime = distance / speed; + +function showTime() { + const hours = Math.floor(travelTime); + console.log(hours); + const minutes = Math.round((travelTime - hours) * 60); + console.log(minutes); + return `${hours} hours and ${minutes} minutes`; +} +console.log(showTime()); // 8 hours and 38 minutes + +// Series duration of my life... +const seriesDurations = [ + { + title: "Game of thrones", + days: 3, + hours: 1, + minutes: 0, + }, + { + title: "Vikings", + days: 7, + hours: 3, + minutes: 29, + }, + { + title: "Good Girls", + days: 1, + hours: 11, + minutes: 0, + }, +]; + +const averageLifeSpan = 80; +const daysInYear = 365; +const hoursInDay = 24; +const minutesInHour = 60; +const averageLifeSpanInMinutes = + averageLifeSpan * daysInYear * hoursInDay * minutesInHour; + +function logOutSeriesText() { + seriesDurations.forEach((series) => { + const seriesDurationInMinutes = + series.days * hoursInDay * minutesInHour + + series.hours * minutesInHour + + series.minutes; + const percentageOfLife = ( + (seriesDurationInMinutes / averageLifeSpanInMinutes) * + 100 + ).toFixed(3); + console.log(`${series.title} took ${percentageOfLife}% of my life`); + }); +} + +const totalPercentage = seriesDurations.reduce((total, series) => { + const seriesDurationInMinutes = + series.days * hoursInDay * minutesInHour + + series.hours * minutesInHour + + series.minutes; + return total + (seriesDurationInMinutes / averageLifeSpanInMinutes) * 100; +}, 0); +console.log(`In total that is ${totalPercentage.toFixed(3)}% of my life`); + +logOutSeriesText(); diff --git a/assets/courses/foundation/intro-to-javascript/week3/cactus.js b/assets/courses/foundation/intro-to-javascript/week3/cactus.js new file mode 100644 index 000000000..2d1306cd9 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week3/cactus.js @@ -0,0 +1,63 @@ +// add activity using date, activity and duration parameters. +const activities = []; +const date = new Date().toISOString().split("T")[0]; +function addActivity(activity, duration) { + activities.push({ + date: date, + activity: activity, + duration: duration, + }); +} + +console.log(addActivity("YouTube", 20)); +console.log(addActivity("Instagram", 40)); +console.log(addActivity("Duolingo", 10)); + +console.log(activities); +console.log(showStatus()); +// if we want to test or trigger add some activities before calling showStatus, +// we also need to make activities 0 by uncommenting add activities + +// created show status function to show total duration, number of activities and date. +function showStatus() { + let totalDuration = 0; + for (let i = 0; i < activities.length; i++) { + totalDuration += activities[i].duration; + } + + if (activities.length === 0) + return "Add some activities before calling showStatus"; + if (totalDuration >= 90) + return `You have reached your limit, no more activities for you!`; + if (activities.length !== 0 && totalDuration < 90) + return `You have added ${activities.length} activities on ${activities[0].date}, which totals to ${totalDuration} minutes.`; +} + +console.log(showStatus()); + +// created spentMostTimeOn function to find the activity with the most time spent. + +function spentMostTimeOn() { + const activityDuration = {}; + + for (let i = 0; i < activities.length; i++) { + const activity = activities[i].activity; + const duration = activities[i].duration; + if (activityDuration[activity]) { + activityDuration[activity] += duration; + } else { + activityDuration[activity] = duration; + } + } + let maxActivity = null; + let maxDuration = 0; + for (const activity in activityDuration) { + if (activityDuration[activity] > maxDuration) { + maxDuration = activityDuration[activity]; + maxActivity = activity; + } + } + return maxActivity; +} + +console.log(`You spent the most time on: ${spentMostTimeOn()}`); diff --git a/assets/courses/foundation/intro-to-javascript/week3/note.js b/assets/courses/foundation/intro-to-javascript/week3/note.js new file mode 100644 index 000000000..7b96a9526 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week3/note.js @@ -0,0 +1,34 @@ +// save a note +const notes = []; +function saveNote(content, id) { + notes.push({ content: content, id: id }); +} + +saveNote("Pick up groceries", 1); +saveNote("Do laundry", 2); + +console.log(notes); + +// get a note + +function getNote(id) { + return notes.find((note) => note.id === id); +} + +const firstNote = getNote(1); +const secondNote = getNote(2); +console.log(firstNote); +console.log(secondNote); + +// log out notes +function logOutNotesFormatted() { + notes.forEach((note) => { + console.log( + `The note with id: ${note.id}, has the following note text: ${note.content}` + ); + }); +} + +logOutNotesFormatted(); + +// codepen https://codepen.io/Iglesia-Desta/pen/yyOombR?editors=1010 diff --git a/assets/courses/foundation/intro-to-javascript/week4/sandbox.txt b/assets/courses/foundation/intro-to-javascript/week4/sandbox.txt new file mode 100644 index 000000000..f92a087ca --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week4/sandbox.txt @@ -0,0 +1,2 @@ +CodeSandbox +https://codesandbox.io/p/devbox/talk-to-your-computer-forked-xsl8vt?workspaceId=ws_99uGEcaND6m1NvYKq1Qadr \ No newline at end of file diff --git a/assets/courses/foundation/intro-to-javascript/week4/voiceasst.js b/assets/courses/foundation/intro-to-javascript/week4/voiceasst.js new file mode 100644 index 000000000..2cd22d134 --- /dev/null +++ b/assets/courses/foundation/intro-to-javascript/week4/voiceasst.js @@ -0,0 +1,99 @@ +const user = {}; // store a user's name and array of names provided through commands. +const todos = []; +function getReply(argument) { + if (!argument || !argument.trim()) return `Please provide a command.`; //if argument is empty or whitespace + const command = argument.toLowerCase(); //converts input command to lowercase to make it case insensitive + + if (command.startsWith("hello my name is ")) { + const name = argument.slice(17).trim().split(" "); //retrieves the name part starting from the 17th character + user.name = name + .map((n) => n.charAt(0).toUpperCase() + n.slice(1)) //capitalizing the first letter and then joining them back into a single string + .join(" "); + + const nameArray = []; // loops through name and creates an array of unique names , storing it in user.nameArray + for (let i = 0; i < name.length; i++) { + if (!nameArray.includes(name[i])) { + nameArray.push(name[i]); + } + } + user.nameArray = nameArray; + return `Nice to meet you ${user.name}`; + } else if (command === "what is my name?") { + // checks if the user's name is stored + if (user.name) { + return `Your name is ${user.name}`; //if name exists it returns name + } else { + return `I don't know your name yet.`; //if name does not exist + } + } else if (command.startsWith("add ")) { + const item = argument.slice(4, command.indexOf(" to my todo")).trim(); + todos.push(item); + return `${item} added to your todo`; + } else if (command.startsWith("remove ")) { + const item = argument.slice(7, command.indexOf(" from my todo")).trim(); + const index = todos.indexOf(item); + if (index > -1) { + todos.splice(index, 1); + return `${item} removed from your todo`; + } else { + return `${item} is not in your todo`; + } + } else if (command === "what is on my todo?") { + if (todos.length === 0) { + return `Your todo is empty.`; + } else { + return `You have ${todos.length} todos - ${todos.join(", ")}`; + } + } else if (command === "what day is it today?") { + const today = new Date(); + const options = { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", + }; + return `Today is ${today.toLocaleDateString("en-US", options)}`; + } else if (command.startsWith("what is ")) { + const expression = argument.slice(8).trim(); + try { + const result = Function(`"use strict"; return (${expression})`)(); + return `The answer is ${result}`; + } catch (error) { + return `I cannot compute that expression.`; + } + } else if (command.startsWith("set a timer for ")) { + const timePart = command.slice(16); + const timeComponents = timePart.split(" "); + const duration = parseInt(timeComponents[0]); + const unit = timeComponents[1]; + let milliseconds = 0; + if (unit === "seconds") { + milliseconds = duration * 1000; + } else if (unit === "minutes") { + milliseconds = duration * 60 * 1000; + } else if (unit === "hours") { + milliseconds = duration * 60 * 60 * 1000; + } + setTimeout(() => { + console.log("Timer done"); + }, milliseconds); + return `Timer set for ${duration} ${unit}`; + } else { + return `Please specify a valid time unit (seconds, minutes, hours).`; + } +} + +console.log(getReply("hello my name is Benjamin L Smith")); +console.log(getReply("What is my name?")); +console.log(getReply("Add fishing to my todo")); +console.log(getReply("Add singing in the shower to my todo")); +console.log(getReply("Remove fishing from my todo")); +console.log(getReply("What is on my todo?")); +console.log(getReply("What day is it today?")); +console.log(getReply("What is + 3")); +console.log(getReply("set a timer for 4 minutes")); +console.log(getReply("Add dancing to my todo")); +console.log(getReply("Add hiking to my todo")); +console.log(getReply("What is 3 * 3")); +console.log(getReply("what is 6 / 2")); +console.log(getReply("what is 6-2")); diff --git a/courses/foundation/intro-to-javascript/README.md b/assets/courses/foundation/intro-to-using-ai/README.md similarity index 100% rename from courses/foundation/intro-to-javascript/README.md rename to assets/courses/foundation/intro-to-using-ai/README.md diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/assets/art-website.PNG b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/art-website.PNG new file mode 100644 index 000000000..bdae836f0 Binary files /dev/null and b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/art-website.PNG differ diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/assets/travel vlog.PNG b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/travel vlog.PNG new file mode 100644 index 000000000..ca0fda005 Binary files /dev/null and b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/travel vlog.PNG differ diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/assets/weather_app.PNG b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/weather_app.PNG new file mode 100644 index 000000000..3e6932a07 Binary files /dev/null and b/assets/courses/foundation/intro-to-using-ai/portfolio/assets/weather_app.PNG differ diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/index.html b/assets/courses/foundation/intro-to-using-ai/portfolio/index.html new file mode 100644 index 000000000..cf354b8c7 --- /dev/null +++ b/assets/courses/foundation/intro-to-using-ai/portfolio/index.html @@ -0,0 +1,168 @@ + + + + + + + + + About Me + + + + +
+
+ profile photo +
+

+ Hello, I am Iglesia +

+

+ A Front-end Developer based in Denmark +

+

+ I am an aspiring travel specialist transitioning into a tech career + with a passion for creating intuitive and visually engaging digital + experiences. Currently living in Denmark, I am actively expanding my + skills through hands-on projects, online courses, and a commitment + to continuous learning. My focus is on mastering key front-end + technologies like HTML, CSS, JavaScript, and modern frameworks such + as React and Vue.js. +

+
+ + +
+
+
+
+
+
+

+ About me👩🏽‍💻 +

+

+ In my free time, I love drawing and visiting places with my + family. I’m passionate about web developing and my goal is to help + clients by creating seamless and visually appealing websites. +

+
+

+ Interests & Skills +

+
+
    +
  • HTML
  • +
  • CSS
  • +
  • JS
  • +
  • GitHub
  • +
  • Python
  • +
+
+
+
+ +
+

+ Projects +

+ +
+
+ + Screenshot of Project 1 + +
+

Project One

+

+ Short one‑sentence description of what the project does and the + tech used. +

+ +
+
+ +
+ + Screenshot of Project 2 + +
+

Project Two

+

+ Brief description highlighting the problem solved or feature + set. +

+ +
+
+ +
+ + Screenshot of Project 3 + +
+

Project Three

+

+ One line about the outcome, results, or what you learned. +

+ +
+
+
+
+ +
+

Contact

+

Want to get in touch? Click below or email me directly.

+ Email Me +
+
+ + + + + + diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/reflection.md b/assets/courses/foundation/intro-to-using-ai/portfolio/reflection.md new file mode 100644 index 000000000..1c2659c65 --- /dev/null +++ b/assets/courses/foundation/intro-to-using-ai/portfolio/reflection.md @@ -0,0 +1,11 @@ +1. I have learned that if AI is prompted the right way it can give us the right solution. + It can also give a more complex solution depending on the AI model. + It can help me explain my mistakes and suggest further improvements.(debugging) + +2. when it gives me a more complex code then I use my own judgement or prompt to give me a simple specific solution. + +3. If we only use the generated code and use it without understanding then we would not learn anything vs if we use it as a learning ground by interacting then we can enhance our knowledge of coding. + +4. Not being able to learn and understand the material + if we don't understand the material chances of becoming a developer will be low. + basically it will limit us from learning diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/script.js b/assets/courses/foundation/intro-to-using-ai/portfolio/script.js new file mode 100644 index 000000000..31a393be4 --- /dev/null +++ b/assets/courses/foundation/intro-to-using-ai/portfolio/script.js @@ -0,0 +1,37 @@ +document.addEventListener("DOMContentLoaded", () => { + let themeButton = document.querySelector(".theme-btn"); + + if (themeButton) { + themeButton.addEventListener("click", changeTheme); + } else { + console.error("Theme button not found"); + } + + function changeTheme() { + let body = document.querySelector("body"); + + if (body.classList.contains("pink")) { + body.classList.remove("pink"); + } else { + body.classList.add("pink"); + } + } +}); + +function contactId() { + let name = prompt("What is your full name?"); + let email = prompt("What is your email address?"); + + if (name.length > 0) { + name = name.charAt(0).toUpperCase() + name.slice(1); + } + + let h1 = document.querySelector("h1"); + h1.innerHTML = + "Thank you for contacting me, " + name + " I will get back to you shortly."; +} + +document.addEventListener("DOMContentLoaded", function () { + let contactButton = document.querySelector(".contact-btn"); + contactButton.addEventListener("click", contactId); +}); diff --git a/assets/courses/foundation/intro-to-using-ai/portfolio/styles.css b/assets/courses/foundation/intro-to-using-ai/portfolio/styles.css new file mode 100644 index 000000000..9af53a9ec --- /dev/null +++ b/assets/courses/foundation/intro-to-using-ai/portfolio/styles.css @@ -0,0 +1,183 @@ +body { + font-family: Arial, sans-serif; + margin: 0 auto; + line-height: 1.6; + background-color: rgb(213, 233, 185); +} + +.pink { + background: rgb(243, 195, 205); +} + +.pink a { + color: white; +} + +nav { + position: fixed; + top: 0px; + width: 100%; + align-items: center; + display: flex; + justify-content: space-between; + background-color: rgba(15, 15, 15, 0.8); + backdrop-filter: blur(10px); + z-index: 1000; +} +.brand { + font-weight: 700; + font-size: 22px; + margin: 20px; + color: white; +} + +.nav li { + list-style: none; + color: white; +} +.nav a { + text-decoration: none; +} +.nav ul { + display: flex; + justify-content: space-evenly; + margin: 20px; + gap: 18px; +} + +.home { + text-align: center; + margin: 50px; + padding: 20px; +} + +.home img { + width: 200px; + border-radius: 50%; +} + +.theme-btn { + background-color: #e5e7eb; + padding: 8px 14px; + border-radius: 6px; + cursor: pointer; +} + +.info-box { + margin: 20px; +} + +.section { + padding: 8em 15%; +} + +main { + max-width: 900px; + width: 100%; + margin: 32px auto; + padding: 20px; +} + +.about { + text-align: center; +} + +.skills li { + list-style: none; +} +.skills ul { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-around; + font-weight: 700px; +} + +.btn { + border: 1px solid #111827; + background: #111827; + color: #fff; + padding: 8px 14px; + border-radius: 6px; + text-decoration: none; + font-size: 14px; +} + +a { + color: inherit; +} +.projects { + max-width: 1100px; + margin: 32px auto; + padding: 0 16px; +} +.projects h2 { + margin: 0 0 16px; +} + +.card-grid { + display: grid; + gap: 16px; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); +} + +.card { + border: 1px solid #e5e7eb; + border-radius: 10px; + background: #fff; + overflow: hidden; + display: flex; + flex-direction: column; + transition: transform 0.12s ease, box-shadow 0.12s ease; +} +.card:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08); +} + +/* Image with fixed ratio */ +.card-media { + display: block; + background: #f3f4f6; +} +.card-media img { + width: 100%; + height: 200px; + object-fit: cover; /* crops to fill area */ + display: block; +} + +.card-body { + padding: 12px 14px; + display: flex; + flex-direction: column; + gap: 8px; +} +.card-title { + margin: 0; + font-size: 18px; +} +.card-desc { + margin: 0; + color: #4b5563; +} + +.card-actions { + margin-top: 4px; +} +footer { + text-align: center; + color: #6b7280; + padding: 24px; + border-top: 1px solid #e5e7eb; + margin-top: 32px; +} + +@media (max-width: 600px) { + .nav li { + display: none; + } + .info-box { + margin: auto; + } +} diff --git a/courses/foundation/intro-to-using-ai/README.md b/assets/courses/foundation/intro-to-web-architecture/README.md similarity index 100% rename from courses/foundation/intro-to-using-ai/README.md rename to assets/courses/foundation/intro-to-web-architecture/README.md diff --git a/courses/foundation/intro-to-web-architecture/README.md b/assets/courses/foundation/team-processes-intro/README.md similarity index 100% rename from courses/foundation/intro-to-web-architecture/README.md rename to assets/courses/foundation/team-processes-intro/README.md diff --git a/assets/courses/foundation/web-architecture-101/README.md b/assets/courses/foundation/web-architecture-101/README.md new file mode 100644 index 000000000..01d94e3f5 --- /dev/null +++ b/assets/courses/foundation/web-architecture-101/README.md @@ -0,0 +1,15 @@ +This is an assignment for week 5 learning Web architecture at hyf + +CRUD Operation flow + +1- CREATE - user submits a recipe -> Front end sends POST ->backend inserts DB -> +frontend shows result + +2- READ - user views recipe -> Front end sends GET -> backend queries DB -> +frontend displays result + +3- UPDATE - user edits recipe -> frontend sends PUT -> backend updates DB -> +frontend shows updated result + +4- DELETE - user deletes recipe -> frontend sends DELETE ->backend removes from DB -> +frontend updates list and displays to user. diff --git a/assets/courses/foundation/web-architecture-101/assets/web arct CREATE updated.PNG b/assets/courses/foundation/web-architecture-101/assets/web arct CREATE updated.PNG new file mode 100644 index 000000000..fab4353a0 Binary files /dev/null and b/assets/courses/foundation/web-architecture-101/assets/web arct CREATE updated.PNG differ diff --git a/assets/courses/foundation/web-architecture-101/assets/web arct DELETE.PNG b/assets/courses/foundation/web-architecture-101/assets/web arct DELETE.PNG new file mode 100644 index 000000000..4895fbc88 Binary files /dev/null and b/assets/courses/foundation/web-architecture-101/assets/web arct DELETE.PNG differ diff --git a/assets/courses/foundation/web-architecture-101/assets/web arct READ update.PNG b/assets/courses/foundation/web-architecture-101/assets/web arct READ update.PNG new file mode 100644 index 000000000..3f8e13a57 Binary files /dev/null and b/assets/courses/foundation/web-architecture-101/assets/web arct READ update.PNG differ diff --git a/assets/courses/foundation/web-architecture-101/assets/web arct UPDATE.PNG b/assets/courses/foundation/web-architecture-101/assets/web arct UPDATE.PNG new file mode 100644 index 000000000..213d6705d Binary files /dev/null and b/assets/courses/foundation/web-architecture-101/assets/web arct UPDATE.PNG differ diff --git a/courses/foundation/team-processes-intro/README.md b/assets/courses/frontend/advanced-javascript/README.md similarity index 100% rename from courses/foundation/team-processes-intro/README.md rename to assets/courses/frontend/advanced-javascript/README.md diff --git a/assets/courses/frontend/advanced-javascript/week1/codewars.txt b/assets/courses/frontend/advanced-javascript/week1/codewars.txt new file mode 100644 index 000000000..f21c5e849 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/codewars.txt @@ -0,0 +1 @@ +https://www.codewars.com/users/Idesta1 \ No newline at end of file diff --git a/assets/courses/frontend/advanced-javascript/week1/doubling.js b/assets/courses/frontend/advanced-javascript/week1/doubling.js new file mode 100644 index 000000000..326af82c7 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/doubling.js @@ -0,0 +1,33 @@ +let numbers = [1, 2, 3, 4]; +let newNumbers = []; + +for (let i = 0; i < numbers.length; i++) { + if (numbers[i] % 2 !== 0) { + newNumbers[i] = numbers[i] * 2; + } +} + +console.log("The doubled numbers are", newNumbers); // [2, 6] + +// using map to double only the odd numbers, + +const doubledArray = numbers.map((number) => { + if (number % 2 !== 0) { + return number * 2; + } + return number; +}); +console.log(doubledArray); + +// filter odd numbers using arrow function +const filtered = numbers.filter((number) => { + return number % 2 !== 0; +}); +console.log(filtered); + +// Filtered and doubled chaining +const filteredAndDoubled = numbers + .filter((number) => number % 2 !== 0) + .map((number) => number * 2); + +console.log(filteredAndDoubled); diff --git a/assets/courses/frontend/advanced-javascript/week1/movie-web/main.js b/assets/courses/frontend/advanced-javascript/week1/movie-web/main.js new file mode 100644 index 000000000..c8f28c4b9 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/movie-web/main.js @@ -0,0 +1,155 @@ +const movies = []; + +fetch("./movies.json") + .then((response) => response.json()) + .then((data) => { + movies.push(...data); + + const movieWithTag = movies.map((movie) => { + let tag; + if (movie.rating >= 7) { + tag = "Good"; + } else if (movie.rating >= 4 && movie.rating < 7) { + tag = "Average"; + } else { + tag = "Bad"; + } + return { + ...movie, + tag: tag, + }; + }); + + const higherRatedMovies = movieWithTag + .filter((movie) => movie.rating >= 6) + .map((movie) => movie.rating); + + const movieCounts = movieWithTag.reduce( + (counts, movie) => { + if (movie.tag === "Good") { + counts.good++; + } else if (movie.tag === "Average") { + counts.average++; + } else if (movie.tag === "Bad") { + counts.bad++; + } + return counts; + }, + { good: 0, average: 0, bad: 0 }, + ); + + document.getElementById("good-movie-count").textContent = movieCounts.good; + document.getElementById("average-movie-count").textContent = + movieCounts.average; + document.getElementById("bad-movie-count").textContent = movieCounts.bad; + + const moviesWithDuplicatedWords = movies.filter((movie) => + hasDuplicatedWord(movie.title), + ); + + console.log( + "Movies with duplicated words in the title:", + moviesWithDuplicatedWords, + ); + + function hasDuplicatedWord(title) { + if (!title) return false; // Handle empty titles + const words = title + .toLowerCase() + .replace(/[^\w\s]/g, "") // Remove punctuation + .split(" "); + const wordSet = new Set(); + + for (const word of words) { + if (wordSet.has(word)) { + return true; // Found a duplicated word + } + wordSet.add(word); + } + return false; // No duplicated words found + } + }) + + .catch((error) => console.error("Error fetching movies:", error)); + +document.addEventListener("DOMContentLoaded", () => { + const shortBtn = document.getElementById("short-btn"); + const longBtn = document.getElementById("long-btn"); + const movieList = document.getElementById("movies-list"); + const startYearInput = document.getElementById("start-year"); + const endYearInput = document.getElementById("end-year"); + const countMoviesBtn = document.getElementById("count-movies-btn"); + const movieCountDiv = document.getElementById("movie-count"); + + function displayMovies(movies, limit = 21) { + movieList.innerHTML = ""; + if (movies.length === 0) { + movieList.textContent = "No movies found."; + return; + } + movies.slice(0, limit).forEach((movie) => { + const movieItem = document.createElement("div"); + movieItem.textContent = `${movie.title} (${movie.year}) `; + movieList.appendChild(movieItem); + }); + } + + shortBtn.addEventListener("click", () => { + const shortTitleMovies = movies.filter((movie) => movie.title.length <= 10); + displayMovies(shortTitleMovies); + }); + + longBtn.addEventListener("click", () => { + const longTitleMovies = movies.filter((movie) => movie.title.length > 10); + displayMovies(longTitleMovies); + }); + + function countMoviesByYearRange(startYear, endYear) { + const moviesInRange = movies.filter( + (movie) => movie.year >= startYear && movie.year <= endYear, + ); + return moviesInRange.length; + } + + countMoviesBtn.addEventListener("click", () => { + const startYear = parseInt(startYearInput.value); + const endYear = parseInt(endYearInput.value); + + if (isNaN(startYear) || isNaN(endYear)) { + movieCountDiv.textContent = "Please enter valid start and end years."; + return; + } + + if (startYear > endYear) { + movieCountDiv.textContent = "Start year cannot be greater than end year."; + return; + } + + const count = countMoviesByYearRange(startYear, endYear); + movieCountDiv.textContent = `Number of movies made between ${startYear}-${endYear}: ${count}`; + }); + + function displayMoviesByKeyword(keyword) { + const moviesWithKeyword = movies.filter((movie) => + movie.title.toLowerCase().includes(keyword.toLowerCase()), + ); + if (moviesWithKeyword.length === 0) { + alert(`No movies found with the keyword "${keyword}".`); + return; + } + displayMovies(moviesWithKeyword); + } + + const keywordInput = document.getElementById("keyword-input"); + const searchBtn = document.getElementById("keyword-btn"); + + searchBtn.addEventListener("click", (event) => { + event.preventDefault(); + const keyword = keywordInput.value.trim(); + if (keyword === "") { + alert("Please enter a keyword to search."); + return; + } + displayMoviesByKeyword(keyword); + }); +}); diff --git a/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.css b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.css new file mode 100644 index 000000000..f6c8a9e93 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.css @@ -0,0 +1,114 @@ +body { + background-color: #282626 !important; + color: #fff !important; +} +img { + max-width: 100%; + height: auto; + padding: 10px; +} + +#short-btn, +#long-btn, +#count-movies-btn { + margin: 10px; + background-color: #e9ecef !important; + color: #198754 !important; + border: 1px solid #198754 !important; + padding: 8px 15px; + border-radius: 10px; + border: none; + cursor: pointer; +} + +#short-btn:hover, +#long-btn:hover, +#count-movies-btn:hover { + background-color: #198754 !important; + color: #fff !important; +} + +#movies-list { + margin-left: 20px; +} +.container { + background-color: #030321 !important; + display: flex; + flex-direction: column; + gap: 20px; + padding: 20px; +} +.top-container { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 20px; +} +.img-fluid { + max-width: 50%; + height: auto; +} +#movies-list-container { + padding: 10px; + border: 1px solid #ccc; + border-radius: 5px; + max-width: 50%; + width: 100%; +} + +#movies-list { + display: flex; + flex-direction: column; + gap: 5px; +} + +#movie-list div { + padding: 5px; + border-bottom: 1px solid #ddd; +} + +#movie-list div:last-child { + border-bottom: none; +} + +/* Media query for small devices like iPhone 14 */ +@media (max-width: 430px) { + body { + font-size: 14px; + } + + .container { + padding: 10px; + } + + .top-container { + flex-direction: column; + align-items: center; + } + + .img-fluid { + max-width: 100%; + } + + #movies-list-container { + max-width: 100%; + padding: 5px; + } + + #short-btn, + #long-btn, + #count-movies-btn { + width: 100%; + margin: 5px 0; + } + + .form-container .row { + flex-direction: column; + gap: 10px; + } + + .form-container .col-md-5, + .form-container .col-md-2 { + width: 100%; + } +} diff --git a/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.html b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.html new file mode 100644 index 000000000..feefa79cd --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.html @@ -0,0 +1,165 @@ + + + + + + + Iglesia's Cinema + + + + +

Iglesia's Cinema

+

+ Welcome to Iglesia's Cinema! We have a great selection of movies for you + to enjoy! +

+ + + + +
+
+ A promotional image for the cinema +
+

Movie List

+
+
+
+ +
+ + +
+ +
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+

Good Movies: 0

+

Average Movies: 0

+

Bad Movies: 0

+
+
+ + + + diff --git a/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.json b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.json new file mode 100644 index 000000000..92b0cea52 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/movie-web/movies.json @@ -0,0 +1,506 @@ +[ + { + "title": "'71", + "year": 2014, + "rating": 7.2, + "votes": 41702, + "running_times": 5940 + }, + { + "title": "'A' gai wak", + "year": 1983, + "rating": 7.4, + "votes": 11942, + "running_times": 6300 + }, + { + "title": "'Breaker' Morant", + "year": 1980, + "rating": 7.9, + "votes": 10702, + "running_times": 6420 + }, + { + "title": "'' Dundee II", + "year": 1988, + "rating": 5.5, + "votes": 47180, + "running_times": 6480 + }, + { + "title": "(500) Days of Summer", + "year": 2009, + "rating": 7.7, + "votes": 412368, + "running_times": 5700 + }, + { + "title": "*batteries not included", + "year": 1987, + "rating": 6.6, + "votes": 25636, + "running_times": 6360 + }, + { + "title": "...E tu vivrai nel terrore! L'aldilà", + "year": 1981, + "rating": 6.9, + "votes": 16484, + "running_times": 5220 + }, + { + "title": "...and justice for all.", + "year": 1979, + "rating": 7.4, + "votes": 25408, + "running_times": 7140 + }, + { + "title": "10", + "year": 1979, + "rating": 6, + "votes": 13152, + "running_times": 7320 + }, + { + "title": "10 Cloverfield Lane", + "year": 2016, + "rating": 7.2, + "votes": 216151, + "running_times": 6240 + }, + { + "title": "10 Items or Less", + "year": 2006, + "rating": 6.7, + "votes": 13342, + "running_times": 4920 + }, + { + "title": "10 Things I Hate About You", + "year": 1999, + "rating": 7.2, + "votes": 247070, + "running_times": 5820 + }, + { + "title": "10 Years", + "year": 2011, + "rating": 6.1, + "votes": 20790, + "running_times": 6000 + }, + { + "title": "10,000 BC", + "year": 2008, + "rating": 5.1, + "votes": 114750, + "running_times": 6540 + }, + { + "title": "100 Feet", + "year": 2008, + "rating": 5.5, + "votes": 10979, + "running_times": 6240 + }, + { + "title": "100 Girls", + "year": 2000, + "rating": 5.9, + "votes": 19232, + "running_times": 5640 + }, + { + "title": "101 Dalmatians", + "year": 1996, + "rating": 5.7, + "votes": 83245, + "running_times": 6180 + }, + { + "title": "102 Dalmatians", + "year": 2000, + "rating": 4.9, + "votes": 28927, + "running_times": 6000 + }, + { + "title": "11-11-11", + "year": 2011, + "rating": 4, + "votes": 11425, + "running_times": 5400 + }, + { + "title": "11:14", + "year": 2003, + "rating": 7.2, + "votes": 40149, + "running_times": 5700 + }, + { + "title": "12 Angry Men", + "year": 1957, + "rating": 8.9, + "votes": 518449, + "running_times": 5760 + }, + { + "title": "12 Rounds", + "year": 2009, + "rating": 5.6, + "votes": 24457, + "running_times": 6480 + }, + { + "title": "12 Years a Slave", + "year": 2013, + "rating": 8.1, + "votes": 513047, + "running_times": 8040 + }, + { + "title": "127 Hours", + "year": 2010, + "rating": 7.6, + "votes": 302809, + "running_times": 5640 + }, + { + "title": "13", + "year": 2010, + "rating": 6.1, + "votes": 36623, + "running_times": 5460 + }, + { + "title": "13 Going on 30", + "year": 2004, + "rating": 6.1, + "votes": 134434, + "running_times": 5880 + }, + { + "title": "13 Hours", + "year": 2016, + "rating": 7.3, + "votes": 85771, + "running_times": 8640 + }, + { + "title": "13 Sins", + "year": 2014, + "rating": 6.3, + "votes": 26738, + "running_times": 5580 + }, + { + "title": "13th", + "year": 2016, + "rating": 8.2, + "votes": 15188, + "running_times": 6000 + }, + { + "title": "1408", + "year": 2007, + "rating": 6.8, + "votes": 228738, + "running_times": 6840 + }, + { + "title": "1492: Conquest of Paradise", + "year": 1992, + "rating": 6.5, + "votes": 24439, + "running_times": 9240 + }, + { + "title": "15 Minutes", + "year": 2001, + "rating": 6.1, + "votes": 44647, + "running_times": 7200 + }, + { + "title": "16 Blocks", + "year": 2006, + "rating": 6.6, + "votes": 117443, + "running_times": 6600 + }, + { + "title": "17 Again", + "year": 2009, + "rating": 6.4, + "votes": 156663, + "running_times": 6120 + }, + { + "title": "1922", + "year": 2017, + "rating": 6.4, + "votes": 15416, + "running_times": 6120 + }, + { + "title": "1941", + "year": 1979, + "rating": 5.9, + "votes": 27172, + "running_times": 8760 + }, + { + "title": "2 Days in New York", + "year": 2012, + "rating": 6, + "votes": 12766, + "running_times": 5760 + }, + { + "title": "2 Days in Paris", + "year": 2007, + "rating": 6.8, + "votes": 28106, + "running_times": 5760 + }, + { + "title": "2 Days in the Valley", + "year": 1996, + "rating": 6.5, + "votes": 16528, + "running_times": 6240 + }, + { + "title": "2 Fast 2 Furious", + "year": 2003, + "rating": 5.9, + "votes": 213674, + "running_times": 6420 + }, + { + "title": "2 Guns", + "year": 2013, + "rating": 6.7, + "votes": 170412, + "running_times": 6540 + }, + { + "title": "20,000 Leagues Under the Sea", + "year": 1954, + "rating": 7.2, + "votes": 24094, + "running_times": 7620 + }, + { + "title": "200 Cigarettes", + "year": 1999, + "rating": 5.9, + "votes": 13532, + "running_times": 6060 + }, + { + "title": "2001 Maniacs", + "year": 2005, + "rating": 5.4, + "votes": 10889, + "running_times": 5220 + }, + { + "title": "2001: A Space Odyssey", + "year": 1968, + "rating": 8.3, + "votes": 481800, + "running_times": 9660 + }, + { + "title": "2001: A Space Travesty", + "year": 2000, + "rating": 3.4, + "votes": 10094, + "running_times": 5940 + }, + { + "title": "2010", + "year": 1984, + "rating": 6.8, + "votes": 44155, + "running_times": 6960 + }, + { + "title": "2012", + "year": 2009, + "rating": 5.8, + "votes": 306797, + "running_times": 9480 + }, + { + "title": "20th Century Women", + "year": 2016, + "rating": 7.4, + "votes": 22965, + "running_times": 7140 + }, + { + "title": "21 & Over", + "year": 2013, + "rating": 5.9, + "votes": 65298, + "running_times": 5580 + }, + { + "title": "21", + "year": 2008, + "rating": 6.8, + "votes": 203251, + "running_times": 7380 + }, + { + "title": "21 Grams", + "year": 2003, + "rating": 7.7, + "votes": 202129, + "running_times": 7440 + }, + { + "title": "21 Jump Street", + "year": 2012, + "rating": 7.2, + "votes": 446476, + "running_times": 6540 + }, + { + "title": "22 Jump Street", + "year": 2014, + "rating": 7.1, + "votes": 292991, + "running_times": 6720 + }, + { + "title": "24 Hour Party People", + "year": 2002, + "rating": 7.4, + "votes": 28750, + "running_times": 7020 + }, + { + "title": "25th Hour", + "year": 2002, + "rating": 7.7, + "votes": 157063, + "running_times": 8100 + }, + { + "title": "27 Dresses", + "year": 2008, + "rating": 6.1, + "votes": 134861, + "running_times": 6660 + }, + { + "title": "28 Days", + "year": 2000, + "rating": 6, + "votes": 37395, + "running_times": 6180 + }, + { + "title": "28 Days Later...", + "year": 2002, + "rating": 7.6, + "votes": 323591, + "running_times": 6780 + }, + { + "title": "28 Weeks Later", + "year": 2007, + "rating": 7, + "votes": 228033, + "running_times": 6000 + }, + { + "title": "2:22", + "year": 2017, + "rating": 5.7, + "votes": 10266, + "running_times": 5880 + }, + { + "title": "3 Days to Kill", + "year": 2014, + "rating": 6.2, + "votes": 75906, + "running_times": 7380 + }, + { + "title": "3 Idiots", + "year": 2009, + "rating": 8.4, + "votes": 256619, + "running_times": 10200 + }, + { + "title": "3 Men and a Baby", + "year": 1987, + "rating": 5.9, + "votes": 39924, + "running_times": 6120 + }, + { + "title": "3 Men and a Little Lady", + "year": 1990, + "rating": 5.3, + "votes": 19005, + "running_times": 6240 + }, + { + "title": "3 Ninjas", + "year": 1992, + "rating": 5.2, + "votes": 17582, + "running_times": 5880 + }, + { + "title": "3 Women", + "year": 1977, + "rating": 7.9, + "votes": 10852, + "running_times": 7440 + }, + { + "title": "30 Days of Night", + "year": 2007, + "rating": 6.6, + "votes": 148004, + "running_times": 6780 + }, + { + "title": "30 Minutes or Less", + "year": 2011, + "rating": 6.1, + "votes": 83073, + "running_times": 4980 + }, + { + "title": "300", + "year": 2006, + "rating": 7.7, + "votes": 654380, + "running_times": 7020 + }, + { + "title": "3000 Miles to Graceland", + "year": 2001, + "rating": 5.9, + "votes": 39646, + "running_times": 7500 + }, + { + "title": "300: Rise of an Empire", + "year": 2014, + "rating": 6.2, + "votes": 245690, + "running_times": 6120 + } +] diff --git a/assets/courses/frontend/advanced-javascript/week1/movie-web/next friday.jpg b/assets/courses/frontend/advanced-javascript/week1/movie-web/next friday.jpg new file mode 100644 index 000000000..93b662508 Binary files /dev/null and b/assets/courses/frontend/advanced-javascript/week1/movie-web/next friday.jpg differ diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/background-img.png b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/background-img.png new file mode 100644 index 000000000..b1da03e83 Binary files /dev/null and b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/background-img.png differ diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/index.html b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/index.html new file mode 100644 index 000000000..5cf6b718f --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/index.html @@ -0,0 +1,42 @@ + + + + + + + + The Fastest Presser Game + + +
+

The Fastest Presser in This Realm

+ + + + + +

Choose Your Input Method:

+ + + +
+ + +
+ +

Press button to begin the game

+
+ +
+ + + + + diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/script.js b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/script.js new file mode 100644 index 000000000..648fadc6c --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/script.js @@ -0,0 +1,120 @@ +let lCount = 0; +let jCount = 0; +let isGameRunning = false; +let useKeyboard = true; // Default to keyboard input + +const statusEl = document.getElementById("status"); +const resultDiv = document.getElementById("result"); +const lButton = document.getElementById("l-btn"); +const jButton = document.getElementById("j-btn"); +const keyboardOption = document.getElementById("keyboard-option"); +const mouseOption = document.getElementById("mouse-option"); +const confetti = new ConfettiGenerator({ + target: "myCanvas", + max: 200, + size: 1, + animate: true, + clock: 25, + rotate: true, + props: ["square", "circle", "triangle", "line"], +}); + +document.getElementById("startBtn").addEventListener("click", () => { + const time = document.getElementById("seconds").value * 1000; + + if (!time || time <= 0) { + return alert("Please insert a correct time"); + } + + // Reset game state + lCount = 0; + jCount = 0; + resultDiv.textContent = ""; + isGameRunning = true; + statusEl.textContent = "Game is running..."; + + setTimeout(() => { + isGameRunning = false; + statusEl.textContent = "Time's up!"; + findWinner(); + }, time); +}); + +// Add event listeners for keyboard and mouse options +keyboardOption.addEventListener("click", () => { + useKeyboard = true; + lButton.disabled = true; + jButton.disabled = true; + statusEl.textContent = "Keyboard mode selected. Press 'L' or 'J' to play."; +}); + +mouseOption.addEventListener("click", () => { + useKeyboard = false; + lButton.disabled = false; + jButton.disabled = false; + statusEl.textContent = + "Mouse mode selected. Click 'L' or 'J' buttons to play."; +}); + +// Keyboard input logic +document.addEventListener("keydown", (event) => { + if (!isGameRunning || !useKeyboard) return; + const key = event.key.toLowerCase(); + if (key === "l") { + lCount++; + checkWinnerWithConfetti(); + } else if (key === "j") { + jCount++; + checkWinnerWithConfetti(); + } +}); + +// Mouse input logic +lButton.addEventListener("click", () => { + if (isGameRunning && !useKeyboard) { + lCount++; + checkWinnerWithConfetti(); + } +}); + +jButton.addEventListener("click", () => { + if (isGameRunning && !useKeyboard) { + jCount++; + checkWinnerWithConfetti(); + } +}); + +function checkWinnerWithConfetti() { + if (lCount > 20 || jCount > 20) { + let winner = lCount > 20 ? "Player L" : "Player J"; + resultDiv.textContent = `${winner} wins with more than 20 presses!`; + + // Trigger confetti + triggerConfetti(); + } +} + +function findWinner() { + let message = ""; + if (lCount > jCount) { + message = `Player L wins with ${lCount} presses!`; + } else if (jCount > lCount) { + message = `Player J wins with ${jCount} presses!`; + } else { + message = "It's a tie!"; + } + resultDiv.textContent = message; +} + +let isConfettiRunning = false; + +function triggerConfetti() { + if (isConfettiRunning) return; // Prevent multiple triggers + isConfettiRunning = true; + + confetti.render(); + setTimeout(() => { + confetti.clear(); + isConfettiRunning = false; // Reset the flag + }, 10000); +} diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/style.css b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/style.css new file mode 100644 index 000000000..b06e2d096 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/week2/fastest presser/style.css @@ -0,0 +1,85 @@ +body { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + width: 100%; + font-family: Arial, sans-serif; + background-image: url("background-img.png"); + background-size: cover; + background-repeat: no-repeat; +} +.game-container { + background-color: rgba(142, 230, 180, 0.586); + padding: 20px; + border-radius: 10px; + text-align: center; +} +#choose-input { + display: block; + margin-bottom: 50px; +} +#keyboard-option, +#mouse-option { + display: inline-block; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; + background-color: brown; + color: white; + border: none; + border-radius: 5px; +} + +#startBtn { + display: inline-block; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; + margin-top: 20px; + background-color: brown; + color: white; + border: none; + border-radius: 5px; +} +#startBtn:hover { + background-color: darkred; +} +.buttons-container { + margin-top: 20px; +} +#l-btn, +#j-btn { + display: inline-block; + padding: 20px 30px; + background: rgb(53, 52, 52); + color: #fff; + border-radius: 5px; + box-shadow: + 0 4px 0 black, + 0 5px 10px rgba(0, 0, 0, 0.2); +} +.status { + margin-top: 20px; + font-size: 18px; + font-weight: bold; +} +.footer { + opacity: 0.7; + font-size: 15px; +} +a { + color: #193cb8; + text-decoration: none; +} +#myCanvas { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; /* Ensures it doesn't block interactions */ + z-index: 10; /* Places it above other elements */ +} diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/functions.js b/assets/courses/frontend/advanced-javascript/week1/week2/functions.js new file mode 100644 index 000000000..5733d0edd --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/week2/functions.js @@ -0,0 +1,122 @@ +//2. functions +// Function that logs a string after a specified delay in seconds +function delayLogOut(delay, stringToLog) { + setTimeout(() => { + console.log(stringToLog); + }, delay * 1000); +} + +console.log(delayLogOut(3, "This string logged after 3 seconds")); + +function earthLogger() { + console.log("Earth"); +} + +function saturnLogger() { + console.log("Saturn"); +} + +function planetLogFunction(logger) { + logger(); +} + +planetLogFunction(earthLogger); +planetLogFunction(saturnLogger); + +function geolocationLogger() { + navigator.geolocation.getCurrentPosition((position) => { + console.log(position); + }); +} + +geolocationLogger(); + +const button = document.getElementById("location-btn"); +const longitude = document.getElementById("longitude-input"); +const latitude = document.getElementById("latitude-input"); + +button.addEventListener("click", geolocationLogger); + +navigator.geolocation.getCurrentPosition((position) => { + latitude.textContent = `This is the Latitude: ${position.coords.latitude}`; + longitude.textContent = `This is the Longitude: ${position.coords.longitude}`; +}); + +function runAfterDelay(delay, callback) { + setTimeout(() => { + callback(); + }, delay * 1000); +} + +runAfterDelay(4, () => { + console.log("This string logged after 4 seconds"); +}); + +function doubleClickDetector(element = document) { + let clickCount = 0; + element.addEventListener("click", () => { + clickCount++; + setTimeout(() => { + if (clickCount === 2) { + console.log("Double click detected!"); + } + clickCount = 0; + }, 500); + }); +} + +const clickElement = document.getElementById("click-element"); +doubleClickDetector(document); + +function jokeCreator(shouldTellFunnyJoke, logFunnyJoke, logBadJoke) { + if (shouldTellFunnyJoke === true) { + logFunnyJoke(); + } else { + logBadJoke(); + } +} + +function logFunnyJoke() { + console.log( + "Why don't scientists trust atoms? Because they make up everything!", + ); +} + +function logBadJoke() { + console.log( + "Why did the scarecrow win an award? Because he was outstanding in his field!", + ); +} + +console.log(jokeCreator(true, logFunnyJoke, logBadJoke)); +console.log(jokeCreator(false, logFunnyJoke, logBadJoke)); + +//3.function as a variable +//create a function in three different ways +const array = [ + () => console.log("Hello"), + () => console.log("Can I get a cake"), + () => console.log("Goodbye"), +]; + +array.forEach((func) => func()); + +// 2 expression function +const SayHi = function () { + console.log("Hi there"); +}; +//normal function +function sayHello() { + console.log("Hello there"); +} +SayHi(); +sayHello(); + +//create object with value function +const obj = { + greet: function () { + console.log("Hello"); + }, +}; + +obj.greet(); diff --git a/assets/courses/frontend/advanced-javascript/week1/week2/index.html b/assets/courses/frontend/advanced-javascript/week1/week2/index.html new file mode 100644 index 000000000..7daa0f7fa --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week1/week2/index.html @@ -0,0 +1,21 @@ + + + + + + week2 assignment 2 + + +

Delay Log Out

+ +

+ + +

+

+ + + + + + diff --git a/assets/courses/frontend/advanced-javascript/week3/image/Currency converter.PNG b/assets/courses/frontend/advanced-javascript/week3/image/Currency converter.PNG new file mode 100644 index 000000000..b28882fed Binary files /dev/null and b/assets/courses/frontend/advanced-javascript/week3/image/Currency converter.PNG differ diff --git a/assets/courses/frontend/advanced-javascript/week3/image/currency.jpg b/assets/courses/frontend/advanced-javascript/week3/image/currency.jpg new file mode 100644 index 000000000..cc7096318 Binary files /dev/null and b/assets/courses/frontend/advanced-javascript/week3/image/currency.jpg differ diff --git a/assets/courses/frontend/advanced-javascript/week3/index.html b/assets/courses/frontend/advanced-javascript/week3/index.html new file mode 100644 index 000000000..460825a86 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week3/index.html @@ -0,0 +1,39 @@ + + + + + + Currency Converter + + + +
+

Currency Converter

+ + + +
+ + +
+ + + +

+
+ + + + + diff --git a/assets/courses/frontend/advanced-javascript/week3/script.js b/assets/courses/frontend/advanced-javascript/week3/script.js new file mode 100644 index 000000000..63f6862d1 --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week3/script.js @@ -0,0 +1,84 @@ +const fromCurrency = document.getElementById("fromCurrency"); +const toCurrency = document.getElementById("toCurrency"); +const amountInput = document.getElementById("amount"); +const convertButton = document.getElementById("convert"); +const swapCurrenciesButton = document.getElementById("swapCurrencies"); +const resultInput = document.getElementById("resultInput"); + +resultInput.readOnly = true; + +/**Fetch exchange rate data for a given base currency */ +async function fetchRateData(baseCurrency) { + const response = await fetch( + `https://open.er-api.com/v6/latest/${baseCurrency}`, + ); + return response.json(); +} + +/**create currency code options and populate the select elements dynamically*/ +function getCurrencyCodes(currencyCodes) { + fromCurrency.innerHTML = ""; + toCurrency.innerHTML = ""; + + currencyCodes.forEach((code) => { + const fromOption = document.createElement("option"); + fromOption.value = code; + fromOption.textContent = code; + fromCurrency.appendChild(fromOption); + + const toOption = document.createElement("option"); + toOption.value = code; + toOption.textContent = code; + toCurrency.appendChild(toOption); + }); + // Set default selections + fromCurrency.value = "EUR"; + toCurrency.value = "DKK"; +} + +/**Fetch the list of currency codes from the API and populate the select elements*/ +async function showCurrencyList() { + try { + const data = await fetchRateData("EUR"); + + const currencyCodes = Object.keys(data.rates).sort(); + + getCurrencyCodes(currencyCodes); + } catch (error) { + console.error("Error loading currency list:", error); + } +} + +// The primary function to convert the currency based on user input and display the result +async function convertCurrency() { + try { + const amount = Number(amountInput.value); + const from = fromCurrency.value; + const to = toCurrency.value; + + if (!Number.isFinite(amount) || amount <= 0) { + resultInput.value = "Please enter a valid amount."; + return; + } + + const data = await fetchRateData(from); + const rates = data.rates[to]; + + const convertedAmount = (amount * rates).toFixed(2); + resultInput.value = convertedAmount; + } catch (error) { + console.error("Error fetching exchange rates:", error); + resultInput.value = + "Error fetching exchange rates. Please try again later."; + } +} + +function swapCurrencies() { + const currentFromCurrency = fromCurrency.value; + fromCurrency.value = toCurrency.value; + toCurrency.value = currentFromCurrency; +} + +convertButton.addEventListener("click", convertCurrency); +swapCurrenciesButton.addEventListener("click", swapCurrencies); +showCurrencyList(); diff --git a/assets/courses/frontend/advanced-javascript/week3/styles.css b/assets/courses/frontend/advanced-javascript/week3/styles.css new file mode 100644 index 000000000..24ca4085a --- /dev/null +++ b/assets/courses/frontend/advanced-javascript/week3/styles.css @@ -0,0 +1,104 @@ +body { + font-family: "Courier New", Courier, monospace; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + width: 100%; + background-image: url("./image/currency.jpg"); + background-size: cover; + background-repeat: no-repeat; +} +main { + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + width: 400px; + height: 400px; + padding: 50px; + background-color: rgba(255, 255, 255, 0.6); + border-radius: 10px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} +input { + width: 300px; + height: 30px; + font-size: 16px; +} +select { + width: 300px; + height: 30px; + font-size: 16px; +} +.actionRow { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; +} + +#swapCurrencies { + width: 48px; + height: 48px; + border: none; + border-radius: 50%; + font-size: 28px; + line-height: 1; + background-color: #ece811; + color: #0a1d56; + cursor: pointer; +} + +#swapCurrencies:hover { + background-color: #fff36c; +} + +#convert { + width: 150px; + height: 40px; + font-size: 16px; + background-color: #0a1d56; + color: #fff; + border-radius: 5px; + cursor: pointer; +} + +#convert:hover { + background-color: #3f86dc; +} +.footer { + color: #fff; + margin-top: 20px; +} +a { + color: #ece811; + text-decoration: none; +} + +@media (max-width: 500px) { + main { + width: 300px; + height: 300px; + padding: 50px; + } + + .actionRow { + width: 100%; + } + + input, + select { + width: 100%; + } + + #convert { + width: 100%; + } + + h1 { + font-size: 22px; + } +} diff --git a/courses/frontend/advanced-javascript/README.md b/assets/courses/frontend/advanced-team-processes/README.md similarity index 100% rename from courses/frontend/advanced-javascript/README.md rename to assets/courses/frontend/advanced-team-processes/README.md diff --git a/courses/frontend/advanced-team-processes/README.md b/assets/courses/frontend/collaboration-via-github/README.md similarity index 100% rename from courses/frontend/advanced-team-processes/README.md rename to assets/courses/frontend/collaboration-via-github/README.md diff --git a/courses/frontend/collaboration-via-github/README.md b/assets/courses/frontend/react/README.md similarity index 100% rename from courses/frontend/collaboration-via-github/README.md rename to assets/courses/frontend/react/README.md diff --git a/assets/courses/frontend/react/space-galactica-app/.env.example b/assets/courses/frontend/react/space-galactica-app/.env.example new file mode 100644 index 000000000..bd53f296b --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/.env.example @@ -0,0 +1 @@ +VITE_NASA_API_KEY=your_nasa_api_key_here \ No newline at end of file diff --git a/courses/frontend/react/space-galactica-app/.gitignore b/assets/courses/frontend/react/space-galactica-app/.gitignore similarity index 65% rename from courses/frontend/react/space-galactica-app/.gitignore rename to assets/courses/frontend/react/space-galactica-app/.gitignore index 8d67a86cd..e866c0f05 100644 --- a/courses/frontend/react/space-galactica-app/.gitignore +++ b/assets/courses/frontend/react/space-galactica-app/.gitignore @@ -1,3 +1,5 @@ .DS_Store node_modules dist +.env +.env.local \ No newline at end of file diff --git a/courses/frontend/react/space-galactica-app/README.md b/assets/courses/frontend/react/space-galactica-app/README.md similarity index 100% rename from courses/frontend/react/space-galactica-app/README.md rename to assets/courses/frontend/react/space-galactica-app/README.md diff --git a/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_partners.png b/assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_partners.png similarity index 100% rename from courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_partners.png rename to assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_partners.png diff --git a/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_team.png b/assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_team.png similarity index 100% rename from courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_team.png rename to assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_team.png diff --git a/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_values.png b/assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_values.png similarity index 100% rename from courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_values.png rename to assets/courses/frontend/react/space-galactica-app/data/inspiration_about_us/our_values.png diff --git a/courses/frontend/react/space-galactica-app/data/mock_data.json b/assets/courses/frontend/react/space-galactica-app/data/mock_data.json similarity index 100% rename from courses/frontend/react/space-galactica-app/data/mock_data.json rename to assets/courses/frontend/react/space-galactica-app/data/mock_data.json diff --git a/courses/frontend/react/space-galactica-app/eslint.config.js b/assets/courses/frontend/react/space-galactica-app/eslint.config.js similarity index 100% rename from courses/frontend/react/space-galactica-app/eslint.config.js rename to assets/courses/frontend/react/space-galactica-app/eslint.config.js diff --git a/courses/frontend/react/space-galactica-app/index.html b/assets/courses/frontend/react/space-galactica-app/index.html similarity index 100% rename from courses/frontend/react/space-galactica-app/index.html rename to assets/courses/frontend/react/space-galactica-app/index.html diff --git a/courses/frontend/react/space-galactica-app/jsconfig.json b/assets/courses/frontend/react/space-galactica-app/jsconfig.json similarity index 100% rename from courses/frontend/react/space-galactica-app/jsconfig.json rename to assets/courses/frontend/react/space-galactica-app/jsconfig.json diff --git a/courses/frontend/react/space-galactica-app/package-lock.json b/assets/courses/frontend/react/space-galactica-app/package-lock.json similarity index 100% rename from courses/frontend/react/space-galactica-app/package-lock.json rename to assets/courses/frontend/react/space-galactica-app/package-lock.json diff --git a/courses/frontend/react/space-galactica-app/package.json b/assets/courses/frontend/react/space-galactica-app/package.json similarity index 100% rename from courses/frontend/react/space-galactica-app/package.json rename to assets/courses/frontend/react/space-galactica-app/package.json diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/CBC_Logo_White.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/CBC_Logo_White.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/CBC_Logo_White.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/CBC_Logo_White.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/Microsoft-Logo-white.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/Microsoft-Logo-white.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/Microsoft-Logo-white.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/Microsoft-Logo-white.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/QueensLogo_white.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/QueensLogo_white.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/QueensLogo_white.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/QueensLogo_white.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/alphabet-logo.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/alphabet-logo.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/alphabet-logo.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/alphabet-logo.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/amazon_logo.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/amazon_logo.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/amazon_logo.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/amazon_logo.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/nyu-logo.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/nyu-logo.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/nyu-logo.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/nyu-logo.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/samsung-logo.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/samsung-logo.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/samsung-logo.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/samsung-logo.png diff --git a/courses/frontend/react/space-galactica-app/public/business_partners/sodexo-logo.png b/assets/courses/frontend/react/space-galactica-app/public/business_partners/sodexo-logo.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/business_partners/sodexo-logo.png rename to assets/courses/frontend/react/space-galactica-app/public/business_partners/sodexo-logo.png diff --git a/courses/frontend/react/space-galactica-app/public/crew/background-crew-desktop.jpg b/assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-desktop.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/background-crew-desktop.jpg rename to assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-desktop.jpg diff --git a/courses/frontend/react/space-galactica-app/public/crew/background-crew-mobile.jpg b/assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-mobile.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/background-crew-mobile.jpg rename to assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-mobile.jpg diff --git a/courses/frontend/react/space-galactica-app/public/crew/background-crew-tablet.jpg b/assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-tablet.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/background-crew-tablet.jpg rename to assets/courses/frontend/react/space-galactica-app/public/crew/background-crew-tablet.jpg diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-douglas-hurley.png b/assets/courses/frontend/react/space-galactica-app/public/crew/image-alex-santos.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-douglas-hurley.png rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-alex-santos.png diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-victor-glover.png b/assets/courses/frontend/react/space-galactica-app/public/crew/image-leo-redding.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-victor-glover.png rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-leo-redding.png diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-victor-glover.webp b/assets/courses/frontend/react/space-galactica-app/public/crew/image-leo-redding.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-victor-glover.webp rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-leo-redding.webp diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.png b/assets/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.png rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.png diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.webp b/assets/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.webp rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-mark-shuttleworth.webp diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-anousheh-ansari.png b/assets/courses/frontend/react/space-galactica-app/public/crew/image-sarah-vega.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-anousheh-ansari.png rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-sarah-vega.png diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-anousheh-ansari.webp b/assets/courses/frontend/react/space-galactica-app/public/crew/image-sarah-vega.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-anousheh-ansari.webp rename to assets/courses/frontend/react/space-galactica-app/public/crew/image-sarah-vega.webp diff --git a/courses/frontend/react/space-galactica-app/public/crew/image-douglas-hurley.webp b/assets/courses/frontend/react/space-galactica-app/public/crew/image.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/crew/image-douglas-hurley.webp rename to assets/courses/frontend/react/space-galactica-app/public/crew/image.webp diff --git a/courses/frontend/react/space-galactica-app/public/destination/background-destination-desktop.jpg b/assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-desktop.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/background-destination-desktop.jpg rename to assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-desktop.jpg diff --git a/courses/frontend/react/space-galactica-app/public/destination/background-destination-mobile.jpg b/assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-mobile.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/background-destination-mobile.jpg rename to assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-mobile.jpg diff --git a/courses/frontend/react/space-galactica-app/public/destination/background-destination-tablet.jpg b/assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-tablet.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/background-destination-tablet.jpg rename to assets/courses/frontend/react/space-galactica-app/public/destination/background-destination-tablet.jpg diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-europa.png b/assets/courses/frontend/react/space-galactica-app/public/destination/image-europa.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-europa.png rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-europa.png diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-europa.webp b/assets/courses/frontend/react/space-galactica-app/public/destination/image-europa.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-europa.webp rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-europa.webp diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-mars.png b/assets/courses/frontend/react/space-galactica-app/public/destination/image-mars.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-mars.png rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-mars.png diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-mars.webp b/assets/courses/frontend/react/space-galactica-app/public/destination/image-mars.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-mars.webp rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-mars.webp diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-moon.png b/assets/courses/frontend/react/space-galactica-app/public/destination/image-moon.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-moon.png rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-moon.png diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-moon.webp b/assets/courses/frontend/react/space-galactica-app/public/destination/image-moon.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-moon.webp rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-moon.webp diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-titan.png b/assets/courses/frontend/react/space-galactica-app/public/destination/image-titan.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-titan.png rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-titan.png diff --git a/courses/frontend/react/space-galactica-app/public/destination/image-titan.webp b/assets/courses/frontend/react/space-galactica-app/public/destination/image-titan.webp similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/image-titan.webp rename to assets/courses/frontend/react/space-galactica-app/public/destination/image-titan.webp diff --git a/courses/frontend/react/space-galactica-app/public/destination/planetary-lineup_3x4.png b/assets/courses/frontend/react/space-galactica-app/public/destination/planetary-lineup_3x4.png similarity index 100% rename from courses/frontend/react/space-galactica-app/public/destination/planetary-lineup_3x4.png rename to assets/courses/frontend/react/space-galactica-app/public/destination/planetary-lineup_3x4.png diff --git a/courses/frontend/react/space-galactica-app/public/home/background-home-desktop.jpg b/assets/courses/frontend/react/space-galactica-app/public/home/background-home-desktop.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/home/background-home-desktop.jpg rename to assets/courses/frontend/react/space-galactica-app/public/home/background-home-desktop.jpg diff --git a/courses/frontend/react/space-galactica-app/public/home/background-home-mobile.jpg b/assets/courses/frontend/react/space-galactica-app/public/home/background-home-mobile.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/home/background-home-mobile.jpg rename to assets/courses/frontend/react/space-galactica-app/public/home/background-home-mobile.jpg diff --git a/courses/frontend/react/space-galactica-app/public/home/background-home-tablet.jpg b/assets/courses/frontend/react/space-galactica-app/public/home/background-home-tablet.jpg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/home/background-home-tablet.jpg rename to assets/courses/frontend/react/space-galactica-app/public/home/background-home-tablet.jpg diff --git a/courses/frontend/react/space-galactica-app/public/shared/icon-close.svg b/assets/courses/frontend/react/space-galactica-app/public/shared/icon-close.svg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/shared/icon-close.svg rename to assets/courses/frontend/react/space-galactica-app/public/shared/icon-close.svg diff --git a/courses/frontend/react/space-galactica-app/public/shared/icon-hamburger.svg b/assets/courses/frontend/react/space-galactica-app/public/shared/icon-hamburger.svg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/shared/icon-hamburger.svg rename to assets/courses/frontend/react/space-galactica-app/public/shared/icon-hamburger.svg diff --git a/courses/frontend/react/space-galactica-app/public/shared/logo.svg b/assets/courses/frontend/react/space-galactica-app/public/shared/logo.svg similarity index 100% rename from courses/frontend/react/space-galactica-app/public/shared/logo.svg rename to assets/courses/frontend/react/space-galactica-app/public/shared/logo.svg diff --git a/assets/courses/frontend/react/space-galactica-app/public/socialmedia/facebook.png b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/facebook.png new file mode 100644 index 000000000..75796ac3a Binary files /dev/null and b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/facebook.png differ diff --git a/assets/courses/frontend/react/space-galactica-app/public/socialmedia/instagram.png b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/instagram.png new file mode 100644 index 000000000..029909d87 Binary files /dev/null and b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/instagram.png differ diff --git a/assets/courses/frontend/react/space-galactica-app/public/socialmedia/linkedin.png b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/linkedin.png new file mode 100644 index 000000000..4fcaa76bf Binary files /dev/null and b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/linkedin.png differ diff --git a/assets/courses/frontend/react/space-galactica-app/public/socialmedia/tiktok.png b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/tiktok.png new file mode 100644 index 000000000..8c301508f Binary files /dev/null and b/assets/courses/frontend/react/space-galactica-app/public/socialmedia/tiktok.png differ diff --git a/courses/frontend/react/space-galactica-app/src/components/Badge.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/Badge.jsx similarity index 100% rename from courses/frontend/react/space-galactica-app/src/components/Badge.jsx rename to assets/courses/frontend/react/space-galactica-app/src/components/Badge.jsx diff --git a/courses/frontend/react/space-galactica-app/src/components/Badge.module.css b/assets/courses/frontend/react/space-galactica-app/src/components/Badge.module.css similarity index 100% rename from courses/frontend/react/space-galactica-app/src/components/Badge.module.css rename to assets/courses/frontend/react/space-galactica-app/src/components/Badge.module.css diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/Footer.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/Footer.jsx new file mode 100644 index 000000000..b863c3436 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/Footer.jsx @@ -0,0 +1,75 @@ +import { useLocation, Link } from "react-router-dom"; +import styles from "./Footer.module.css"; +import { SocialMediaItem } from "./SocialMediaItem"; + +const socialMediaLItems = [ + { + id: 1, + title: "Facebook", + url: "https://facebook.com", + icon: "/socialmedia/facebook.png", + }, + { + id: 2, + title: "Instagram", + url: "https://instagram.com", + icon: "/socialmedia/instagram.png", + }, + { + id: 3, + title: "Tiktok", + url: "https://tiktok.com", + icon: "/socialmedia/tiktok.png", + }, + { + id: 4, + title: "LinkedIn", + url: "https://www.linkedin.com/feed/", + icon: "/socialmedia/linkedin.png", + }, +]; + +export const Footer = () => { + const { pathname } = useLocation(); + + return ( + + ); +}; diff --git a/courses/frontend/react/space-galactica-app/src/components/Footer.module.css b/assets/courses/frontend/react/space-galactica-app/src/components/Footer.module.css similarity index 67% rename from courses/frontend/react/space-galactica-app/src/components/Footer.module.css rename to assets/courses/frontend/react/space-galactica-app/src/components/Footer.module.css index 1e27a02a9..c775b8381 100644 --- a/courses/frontend/react/space-galactica-app/src/components/Footer.module.css +++ b/assets/courses/frontend/react/space-galactica-app/src/components/Footer.module.css @@ -16,7 +16,9 @@ padding: var(--spacing-08) 0; } -.footer p, .footer a, .footer li { +.footer p, +.footer a, +.footer li { color: #000; font-size: medium; font-weight: 200; @@ -43,3 +45,23 @@ .footerList li { padding-block: var(--spacing-04); } +.footerListItem { + padding-block: var(--spacing-04); +} + +.footerListItem img { + width: 24px; + height: 24px; + object-fit: contain; + display: block; +} + +.pages ul { + list-style: none; + padding: 0; + margin: 0; +} + +.pages li { + padding-block: var(--spacing-04); +} diff --git a/courses/frontend/react/space-galactica-app/src/components/Layout.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/Layout.jsx similarity index 70% rename from courses/frontend/react/space-galactica-app/src/components/Layout.jsx rename to assets/courses/frontend/react/space-galactica-app/src/components/Layout.jsx index bf77e0217..f142de330 100644 --- a/courses/frontend/react/space-galactica-app/src/components/Layout.jsx +++ b/assets/courses/frontend/react/space-galactica-app/src/components/Layout.jsx @@ -1,5 +1,6 @@ import { Outlet } from "react-router-dom"; import { Navbar } from "./Navbar.jsx"; +import { Footer } from "./Footer.jsx"; export const metadata = { title: "Galactica", @@ -11,10 +12,9 @@ export const RootLayout = () => {
- {/* 🧑🏽‍🚀 Task - Week 1 */} - {/* Import and use the Footer component here. */} +
); -} +}; -export default RootLayout; \ No newline at end of file +export default RootLayout; diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/NavItem.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/NavItem.jsx new file mode 100644 index 000000000..9cdeb0b60 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/NavItem.jsx @@ -0,0 +1,17 @@ +import classNames from "classnames"; +import styles from "./Navbar.module.css"; +import { Link } from "react-router-dom"; + +export const NavItem = ({ title, link, isActive }) => { + return ( +
  • + {title} +
  • + ); +}; + +export default NavItem; diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/Navbar.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/Navbar.jsx new file mode 100644 index 000000000..33c4447c3 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/Navbar.jsx @@ -0,0 +1,54 @@ +import { useLocation } from "react-router-dom"; +import { Planet } from "../icons/Planet"; +import { Badge } from "./Badge"; +import styles from "./Navbar.module.css"; +import { NavItem } from "./NavItem"; + +const navbarItems = [ + { + title: "01 ABOUT", + link: "/about_us", + }, + { + title: "02 DESTINATION", + link: "/destination", + }, + { + title: "03 NASA COLLABORATION", + link: "/nasa_collaboration", + }, +]; + +export const Navbar = () => { + const currentPath = useLocation().pathname; + + return ( +
    +
    + + GALACTICA + +
    +
    + +
    + ); +}; diff --git a/courses/frontend/react/space-galactica-app/src/components/Navbar.module.css b/assets/courses/frontend/react/space-galactica-app/src/components/Navbar.module.css similarity index 89% rename from courses/frontend/react/space-galactica-app/src/components/Navbar.module.css rename to assets/courses/frontend/react/space-galactica-app/src/components/Navbar.module.css index fd3cfa1d1..57b4fdc42 100644 --- a/courses/frontend/react/space-galactica-app/src/components/Navbar.module.css +++ b/assets/courses/frontend/react/space-galactica-app/src/components/Navbar.module.css @@ -45,7 +45,6 @@ padding: 0 var(--spacing-8); margin: var(--spacing-20); background-color: transparent; - } .navbarBG { @@ -71,7 +70,17 @@ letter-spacing: 1px; } -.navbarLinks:hover, .isLinkActive { +.navbarLinks:hover, +.isLinkActive { border-block-end: var(--spacing-04) solid var(--border-color); margin-block-end: -4px; } + +@media (max-width: 768px) { + .navbarLogo { + display: none; + } + .navbarLinks a { + font-size: 12px; + } +} diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.jsx new file mode 100644 index 000000000..fb6507fc0 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.jsx @@ -0,0 +1,17 @@ +import styles from "./RoverPhoto.module.css"; + +export default function RoverPhoto({ src, date, roverName }) { + return ( +
    +
    + {`Rover +
    +

    {`Rover: ${roverName}`}

    +

    {`Date: ${date}`}

    +
    + ); +} diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.module.css b/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.module.css new file mode 100644 index 000000000..905a795af --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/RoverPhoto.module.css @@ -0,0 +1,32 @@ +.roverCard { + width: min(100%, 700px); + border: 1px solid rgba(255, 255, 255, 0.14); + border-radius: 14px; + padding: 0.9rem; + background: rgba(5, 10, 24, 0.72); +} + +.imageWrap { + border-radius: 10px; + overflow: hidden; + background: #030710; +} + +.roverImage { + width: 100%; + max-height: 420px; + object-fit: cover; + display: block; +} + +.meta { + margin: 0.6rem 0 0; + color: #d4dcff; + font-size: 0.95rem; +} + +@media (max-width: 768px) { + .roverImage { + width: 100%; + } +} diff --git a/assets/courses/frontend/react/space-galactica-app/src/components/SocialMediaItem.jsx b/assets/courses/frontend/react/space-galactica-app/src/components/SocialMediaItem.jsx new file mode 100644 index 000000000..535199eb1 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/components/SocialMediaItem.jsx @@ -0,0 +1,14 @@ +import { useLocation, Link } from "react-router-dom"; +import styles from "./Footer.module.css"; + +export const SocialMediaItem = ({ url, title, icon }) => { + return ( +
  • + + {title} + +
  • + ); +}; + +export default SocialMediaItem; diff --git a/courses/frontend/react/space-galactica-app/src/favicon.ico b/assets/courses/frontend/react/space-galactica-app/src/favicon.ico similarity index 100% rename from courses/frontend/react/space-galactica-app/src/favicon.ico rename to assets/courses/frontend/react/space-galactica-app/src/favicon.ico diff --git a/courses/frontend/react/space-galactica-app/src/icons/Planet.jsx b/assets/courses/frontend/react/space-galactica-app/src/icons/Planet.jsx similarity index 100% rename from courses/frontend/react/space-galactica-app/src/icons/Planet.jsx rename to assets/courses/frontend/react/space-galactica-app/src/icons/Planet.jsx diff --git a/courses/frontend/react/space-galactica-app/src/main.css b/assets/courses/frontend/react/space-galactica-app/src/main.css similarity index 83% rename from courses/frontend/react/space-galactica-app/src/main.css rename to assets/courses/frontend/react/space-galactica-app/src/main.css index 478c588ca..7be9d004d 100644 --- a/courses/frontend/react/space-galactica-app/src/main.css +++ b/assets/courses/frontend/react/space-galactica-app/src/main.css @@ -1,7 +1,8 @@ :root { --max-width: 1100px; --border-radius: 12px; - --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", + --font-mono: + ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace; @@ -11,7 +12,7 @@ --primary-background-color: #000; --primary-text-color: #fff; - --border-color: #eee; + --border-color: #000051; --card-bg-color: rgba(100, 100, 100, 0.3); --primary-glow: conic-gradient( @@ -87,7 +88,6 @@ body { overflow-x: hidden; } - body { color: rgb(var(--foreground-rgb)); background: linear-gradient( @@ -103,12 +103,19 @@ a { text-decoration: none; } -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { margin-block-end: var(--spacing-08); color: var(--primary-text-color); } -p, b, i { +p, +b, +i { margin-block-end: var(--spacing-08); } @@ -136,7 +143,6 @@ button { color: #fff; } - .card { position: relative; padding: var(--spacing-12); @@ -172,7 +178,6 @@ button { font-weight: 200; letter-spacing: 4px; } - .roundButton { padding: var(--spacing-08); height: 100px; @@ -181,18 +186,33 @@ button { min-width: 100px; line-height: 1.2; cursor: pointer; - background-color: white; - color: black; + background-color: #ffce48; + border: none; + color: #444242; border-radius: 50%; - font-size: var(--font-size-3xs); + font-size: 10px; font-weight: 700; letter-spacing: 0.5px; display: flex; align-items: center; justify-content: center; text-align: center; - word-wrap: break-word; + word-break: break-word; overflow-wrap: break-word; + transition: 0.3s; + cursor: pointer; + /* Initial glow */ + box-shadow: + 0 0 10px #ffce48, + 0 0 40px #ffce48; +} + +.roundButton:hover { + /* Intensified glow on hover */ + box-shadow: + 0 0 20px #ffce48, + 0 0 60px #ffce48; + transform: scale(1.05); } .fullBGpicture { @@ -206,7 +226,7 @@ button { .fullBGpicture::before { content: ""; - background: url('/destination/background-destination-desktop.jpg') no-repeat; + background: url("/destination/background-destination-desktop.jpg") no-repeat; background-size: cover; background-position: center; background-color: #000; @@ -231,3 +251,16 @@ button { justify-content: space-between; min-height: 100vh; } + +@media (max-width: 600px) { + .roundButton { + padding: var(--spacing-04); + height: 45px; + width: 45px; + min-height: 45px; + min-width: 45px; + border-radius: 4px; + font-size: 10px; + padding: var(--spacing-04); + } +} diff --git a/courses/frontend/react/space-galactica-app/src/main.jsx b/assets/courses/frontend/react/space-galactica-app/src/main.jsx similarity index 100% rename from courses/frontend/react/space-galactica-app/src/main.jsx rename to assets/courses/frontend/react/space-galactica-app/src/main.jsx diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.jsx new file mode 100644 index 000000000..3d0aa2ede --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.jsx @@ -0,0 +1,28 @@ +import styles from "./AboutUsPage.module.css"; +import OurValues from "./OurValues"; +import OurCrew from "./OurCrew"; +import OurPartners from "./OurPartners"; + +export const Crew = () => { + return ( +
    +
    +

    About us

    +
    +

    Our Values

    + +
    +
    +

    The Crew

    + +
    +
    +

    Our Partners

    + +
    +
    +
    + ); +}; + +export default Crew; diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.module.css b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.module.css new file mode 100644 index 000000000..e84b96ffb --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/AboutUsPage.module.css @@ -0,0 +1,125 @@ +.app { + background-color: black; + width: 100vw; + height: 100vh; +} + +h1 { + font-weight: 200; +} + +h2 { + font-size: 21px; + opacity: 0.9; +} + +p { + font-size: 14px; +} + +.valuesContainer { + display: grid; + grid-template-columns: repeat(2, 1fr); + background-color: #080c24; + padding: 30px; + gap: 20px; + margin-top: 30px; +} + +.valueCard { + background: #111; + border: 1px solid #2f2f2f; + border-radius: 12px; + padding: 18px; +} + +.valueNumber { + font-size: 3rem; + font-weight: 200; + line-height: 1; + margin: 0 0 8px; + color: #ffffff; + opacity: 0.9; +} + +.valueTitle { + font-size: 1.05rem; + margin: 0 0 10px; + color: #ffffff; +} + +.valueDescription { + font-size: 0.9rem; + line-height: 1.5; + margin: 0; + color: #d4d4d4; +} + +.crewGrid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; + margin-top: 24px; +} + +.crewCard { + border: 1px solid #333; + border-radius: 12px; + padding: 16px; + background: #111; + color: #fff; +} + +.crewImage { + width: 100%; + max-width: 220px; + height: auto; + display: block; + margin-bottom: 12px; +} + +.partnersGrid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; + margin-top: 30px; + align-items: center; +} + +.partnerLogo { + width: 100%; + max-width: 150px; + display: block; + margin: 0 auto; +} + +@media (max-width: 768px) { + .valuesContainer { + grid-template-columns: 1fr; + font-size: 12px; + } + .valueCard { + padding: 14px; + font-size: 12px; + } + .valueNumber { + font-size: 1.8rem; + } + + .crewGrid { + grid-template-columns: 1fr; + } + .crewCard { + padding: 14px; + font-size: 12px; + } + .crewImage { + max-width: 180%; + margin-left: auto; + margin-right: auto; + } + .partnerLogo { + max-width: 120px; + width: 70px; + } +} diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurCrew.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurCrew.jsx new file mode 100644 index 000000000..9cd40dcbe --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurCrew.jsx @@ -0,0 +1,64 @@ +import styles from "./AboutUsPage.module.css"; + +const crewMembers = [ + { + id: 1, + name: "Captain Sarah Vega", + Title: "Astronaut", + description: + "A former NASA astronaut with over 15 years of experience, Captain Vega leads our missions with unparalleled expertise and a passion for space exploration.", + image: "/crew/image-sarah-vega.png", + }, + { + id: 2, + name: "Dr.Leo Redding", + Title: "Chief astroPhysicist", + description: + "Dr. Redding is a renowned astrophysicist whose groundbreaking research on black holes and dark matter has earned him international acclaim.", + image: "/crew/image-leo-redding.png", + }, + { + id: 3, + name: " Mark Shuttleworth", + Title: "Chief Engineer", + description: + "With his extensive background in aerospace engineering, He is responsible for the state-of-the-art technology that powers our spacecraft. Her innovation ensures that our travelers are always in safe hands.", + image: "/crew/image-mark-shuttleworth.png", + }, + { + id: 4, + name: "Alex Santos", + Title: "Mission Specialist", + description: + " As a mission specialist, Alex’s job is to ensure that every aspect of the journey runs smoothly. With a background in both science and adventure tourism, Alex is the perfect guide for our space travelers.", + image: "/crew/image-alex-santos.png", + }, +]; + +const OurCrew = () => { + return ( +
    +

    + Our crew is the heart and soul of Galactica. We are a diverse team of + seasoned space explorers, engineers, and visionaries who are united by a + common goal: to make space travel accessible and exciting for all. +

    +
    + {crewMembers.map((member) => ( +
    + {member.name} +

    {member.name}

    +

    {member.Title}

    +

    {member.description}

    +
    + ))} +
    +
    + ); +}; + +export default OurCrew; diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurPartners.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurPartners.jsx new file mode 100644 index 000000000..0cc4591b5 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurPartners.jsx @@ -0,0 +1,52 @@ +import styles from "./AboutUsPage.module.css"; + +const partners = [ + { + id: 1, + image: "/business_partners/amazon_logo.png", + }, + { + id: 2, + image: "/business_partners/CBC_Logo_White.png", + }, + + { + id: 3, + image: "/business_partners/nyu-logo.png", + }, + { + id: 4, + image: "/business_partners/QueensLogo_white.png", + }, + { + id: 5, + image: "/business_partners/samsung-logo.png", + }, + { + id: 6, + image: "/business_partners/sodexo-logo.png", + }, +]; + +const OurPartners = () => { + return ( +
    +

    + We collaborate with some of the most respected names in the space and + technology industries to make every journey extraordinary. +

    +
    + {partners.map((partner) => ( + {`Partner + ))} +
    +
    + ); +}; + +export default OurPartners; diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurValues.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurValues.jsx new file mode 100644 index 000000000..b51df5a9d --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/OurValues.jsx @@ -0,0 +1,49 @@ +import styles from "./AboutUsPage.module.css"; + +const values = [ + { + number: "01", + title: "Exploration", + description: + "We are driven by a deep-seated desire to explore the unknown. We believe that the pursuit of discovery is at the heart of human nature, and we are committed to pushing the boundaries of what is possible.", + }, + { + number: "02", + title: "Innovation", + description: + "At Galactica, we prioritize cutting-edge technology and innovation. We are constantly evolving our spacecraft, safety protocols, and services to ensure that our travelers experience the most advanced and secure space journeys available.", + }, + { + number: "03", + title: "Sustainability", + description: + "We are committed to making space exploration sustainable for future generations. Our space missions are designed to minimize environmental impact, both on Earth and in space, and to foster a spirit of responsibility towards our universe.", + }, + { + number: "04", + title: "Community", + description: + "We believe in the power of collective exploration. Our journeys are not just about reaching new destinations; they are about building a community of space enthusiasts who share a passion for the stars.", + }, +]; + +const OurValues = () => { + return ( +
    +

    Rules To Live By.

    +
    +
    + {values.map((value) => ( +
    +

    {value.number}

    +

    {value.title}

    +

    {value.description}

    +
    + ))} +
    +
    +
    + ); +}; + +export default OurValues; diff --git a/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/README.md b/assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/README.md similarity index 100% rename from courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/README.md rename to assets/courses/frontend/react/space-galactica-app/src/pages/AboutUsPage/README.md diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/AddWishlistItem.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/AddWishlistItem.jsx new file mode 100644 index 000000000..f9c37f1d0 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/AddWishlistItem.jsx @@ -0,0 +1,42 @@ +import { useState } from "react"; +import styles from "./DestinationPage.module.css"; + +export const AddWishlistItem = ({ onAddWishlistItem }) => { + const [thumbnail, setThumbnail] = useState("/destination/image-europa.png"); + const [customWishlistItem, setCustomWishlistItem] = useState(""); + + const onAddItemPressed = (e) => { + e.preventDefault(); + if (customWishlistItem.trim() === "") { + return; + } + onAddWishlistItem(customWishlistItem, thumbnail); + setCustomWishlistItem(""); + setThumbnail("/destination/image-europa.png"); + }; + + return ( +
    +

    Add custom planet to wishlist

    + + setCustomWishlistItem(e.target.value)} + /> + + + +
    + ); +}; diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.jsx new file mode 100644 index 000000000..d42d615d3 --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.jsx @@ -0,0 +1,130 @@ +import { useState } from "react"; +import styles from "./DestinationPage.module.css"; +import PlanetCard from "./PlanetCard"; +import { AddWishlistItem } from "./AddWishlistItem"; + +const planetsData = [ + { + name: "Europa", + description: + "Europa, one of Jupiter’s moons, is an icy world with a hidden ocean beneath its surface. This mysterious moon is a prime candidate for the search for extraterrestrial life, making it a thrilling destination for space explorers.", + thumbnail: "/destination/image-europa.png", + }, + { + name: "Mars", + description: + "Mars, the Red Planet, is a barren yet fascinating world with vast deserts, towering volcanoes, and the deepest canyon in the solar system. As humanity’s next frontier, Mars invites us to dream of colonization and the possibilities of life beyond Earth.", + thumbnail: "/destination/image-mars.png", + }, + { + name: "Moon", + description: + "Our closest celestial neighbor, the Moon, is a silent witness to Earth's history. With its stunning craters and desolate landscapes, the Moon offers a unique glimpse into space exploration's past and future, making it a perfect destination for lunar adventurers.", + thumbnail: "/destination/image-moon.png", + }, + { + name: "Titan", + description: + "Titan, Saturn's largest moon, is a world of dense atmosphere and liquid methane lakes. This enigmatic moon is shrouded in a thick orange haze, concealing a landscape that is both alien and strangely familiar, beckoning explorers to uncover its secrets.", + thumbnail: "/destination/image-titan.png", + }, +]; + +const PlanetsWishlistItem = ({ name, thumbnail, onRemove }) => { + return ( +
    + {name} + {name.toUpperCase()} + +
    + ); +}; + +export const Destinations = () => { + const [planetsWishlist, setPlanetsWishlist] = useState([]); + + const isPlanetInWishlist = (planetName) => { + return planetsWishlist.some((planet) => planet.name === planetName); + }; + + const togglePlanetSelection = (name, thumbnail) => { + if (isPlanetInWishlist(name)) { + removePlanetFromWishlist(name); + } else { + addPlanetToWishlist(name, thumbnail); + } + }; + + const addPlanetToWishlist = (name, thumbnail) => { + setPlanetsWishlist((prevWishlist) => [ + ...prevWishlist, + { name, thumbnail }, + ]); + }; + const removePlanetFromWishlist = (name) => { + setPlanetsWishlist((prevWishlist) => + prevWishlist.filter((planet) => planet.name !== name), + ); + }; + + const wishlistCount = planetsWishlist.length; + + return ( +
    +
    +

    Travel Destinations

    +
    +

    WishList

    + + {wishlistCount === 0 ? ( +

    + No planets in your wishlist{" "} + 👩🏽‍🚀 +

    + ) : ( +

    + You have{" "} + {wishlistCount}{" "} + planets in your wishlist +

    + )} + + + + {planetsWishlist.map((planet) => ( + removePlanetFromWishlist(planet.name)} + /> + ))} +
    +
    +

    Possible Destinations

    + {planetsData.map((planet) => ( + + ))} +
    +
    +
    + ); +}; + +export default Destinations; + +// 🧑🏽‍🚀 Task - Week 4 - part 2 +// Hate to break it to you, but you will have to make some changes to the code you already wrote. +// Now that you have context, grab and use the context data in this. +// You will need to replace some of the variables and functions with the ones from the context. diff --git a/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css similarity index 69% rename from courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css rename to assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css index 4ad132f47..26e0e0f60 100644 --- a/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/DestinationPage.module.css @@ -57,6 +57,15 @@ margin: var(--spacing-16) 0; } +.wishlistCount { + color: #ffd54a; +} + +.astroIcon { + font-size: 2.35em; + line-height: 1; +} + .addWishlistItem { border: 1px solid var(--border-color); width: 200px; @@ -77,8 +86,42 @@ font-size: small; } -.addWishlistItem input, +.addWishlistItem input, .addWishlistItem select { height: 30px; margin-block-end: var(--spacing-20); -} \ No newline at end of file +} + +@media (max-width: 768px) { + .planetCard { + flex-direction: column; + align-items: stretch; + gap: var(--spacing-12); + padding: var(--spacing-12); + max-width: 100%; + align-items: flex-start; + } + + .planetCard:nth-child(odd) { + margin-inline-start: 0; + } + + .planetCard > *:last-child { + margin-inline-start: 0; + width: 100%; + } + + .planetDescription { + padding-block-start: 0; + } + + .planetThumbnail { + width: 96px; + height: 96px; + margin: 0; + } + + .wishlistList { + flex-wrap: wrap; + } +} diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/PlanetCard.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/PlanetCard.jsx new file mode 100644 index 000000000..5549d208d --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/PlanetCard.jsx @@ -0,0 +1,30 @@ +import styles from "./DestinationPage.module.css"; + +const PlanetCard = ({ + name, + description, + thumbnail, + isSelected, + togglePlanetSelection, +}) => { + return ( +
    + +
    +

    + {name.toUpperCase()} + {isSelected ? "- SELECTED" : ""} +

    +

    {description}

    +
    + +
    + ); +}; + +export default PlanetCard; diff --git a/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/README.md b/assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/README.md similarity index 100% rename from courses/frontend/react/space-galactica-app/src/pages/DestinationPage/README.md rename to assets/courses/frontend/react/space-galactica-app/src/pages/DestinationPage/README.md diff --git a/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.jsx similarity index 100% rename from courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.jsx rename to assets/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.jsx diff --git a/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.module.css b/assets/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.module.css similarity index 100% rename from courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.module.css rename to assets/courses/frontend/react/space-galactica-app/src/pages/HomePage/HomePage.module.css diff --git a/assets/courses/frontend/react/space-galactica-app/src/pages/NasaCollaborationPage/NasaCollaborationPage.jsx b/assets/courses/frontend/react/space-galactica-app/src/pages/NasaCollaborationPage/NasaCollaborationPage.jsx new file mode 100644 index 000000000..0966b0fcf --- /dev/null +++ b/assets/courses/frontend/react/space-galactica-app/src/pages/NasaCollaborationPage/NasaCollaborationPage.jsx @@ -0,0 +1,130 @@ +import React, { useState, useEffect } from "react"; +import styles from "./NasaCollaborationPage.module.css"; +import RoverPhoto from "../../components/RoverPhoto"; + +// Read "/app/nasa_collaboration/README.md" for more info about the API_KEY +// You need a proper API_KEY for the requests to work +const API_KEY = import.meta.env.VITE_NASA_API_KEY; +const yesterday = new Date(); +yesterday.setDate(yesterday.getDate() - 1); +const latestDate = yesterday.toISOString().split("T")[0]; +const MAX_ROVER_PHOTOS = 1; + +const NASA_URLs = { + astronomyPicOfTheDay: `https://api.nasa.gov/planetary/apod?api_key=${API_KEY}`, + marsRoverPhoto: `https://rovers.nebulum.one/api/v1/rovers/curiosity/photos?earth_date=${latestDate}&api_key=${API_KEY}`, +}; + +export const NasaCollaboration = () => { + const [dailyImg, setDailyImg] = useState({}); + const [roverPhoto, setRoverPhoto] = useState([]); + const [isLoadingRoverPhotos, setIsLoadingRoverPhotos] = useState(true); + const [roverError, setRoverError] = useState(""); + const [isLoadingDailyImg, setIsLoadingDailyImg] = useState(true); + const [dailyImgError, setDailyImgError] = useState(""); + + useEffect(() => { + const fetchRoverPhotos = async () => { + try { + setIsLoadingRoverPhotos(true); + setRoverError(""); + + const roverPhotoResponse = await fetch(NASA_URLs.marsRoverPhoto); + const data = await roverPhotoResponse.json(); + + setRoverPhoto(data.photos.slice(0, MAX_ROVER_PHOTOS) || []); + } catch (error) { + setRoverError("Failed to fetch rover photos. Please try again later."); + } finally { + setIsLoadingRoverPhotos(false); + } + }; + fetchRoverPhotos(); + + const fetchDailyImg = async () => { + try { + setIsLoadingDailyImg(true); + setDailyImgError(""); + + const dailyImgResponse = await fetch(NASA_URLs.astronomyPicOfTheDay).then( + (response) => response.json(), + ); + setDailyImg(dailyImgResponse); + } catch (error) { + setDailyImgError("Failed to fetch astronomy picture. Please try again later."); + } finally { + setIsLoadingDailyImg(false); + } + }; + + fetchDailyImg(); + }, []); + + return ( +
    +
    +

    Collaboration with NASA

    + +
    +

    Astronomy Picture of the day

    + + {isLoadingDailyImg ? ( +

    Loading astronomy picture...

    + ) : dailyImgError ? ( +

    {dailyImgError}

    + ) : ( + <> +

    {dailyImg.title}

    + +
    + {dailyImg.media_type === "image" ? ( + {dailyImg.title} + ) : dailyImg.media_type === "video" ? ( +