diff --git a/challenges/challenge-cowsay-two/solution1.js b/challenges/challenge-cowsay-two/solution1.js index a7f2416b..616e6b2d 100644 --- a/challenges/challenge-cowsay-two/solution1.js +++ b/challenges/challenge-cowsay-two/solution1.js @@ -1,30 +1,35 @@ -// ================= -// Stripped down cowsayer CLI, -// no libraries -// https://nodejs.dev/learn/nodejs-accept-arguments-from-the-command-line -// ================= +// cowsay.js // 1. Accept arguments +const userInput = process.argv.slice(2).join(' '); + +// 2. Make speech bubble +function makeBubble(text) { + if (!text) text = "Moo!"; + const len = text.length; + const top = ' ' + '_'.repeat(len + 2); + const middle = `| ${text} |`; + const bottom = ' ' + '-'.repeat(len + 2); + return `${top}\n${middle}\n${bottom}`; +} -// how will you accept arguments? - -// 2. Make supplies for our speech bubble - -let topLine = '_'; -let bottomLine = '-'; -let saying = ''; - -// 3. Make a cow that takes a string +// 3. Make a simple cow +function makeCow() { + return ` + \\ ^__^ + \\ (oo)\\_______ + (__)\\ )\\/\\ + ||----w | + || || + `; +} +// 4. Combine bubble + cow function cowsay(saying) { -// how will you make the speech bubble contain the text? - -// where will the cow picture go? - -// how will you account for the parameter being empty? - + const bubble = makeBubble(saying); + const cow = makeCow(); + return bubble + cow; } -//4. Pipe argument into cowsay function and return a cow - -// how will you log this to the console? +// 5. Log to console +console.log(cowsay(userInput)); diff --git a/challenges/challenge-cowsay-two/solution2.js b/challenges/challenge-cowsay-two/solution2.js index 8aca8572..cec709da 100644 --- a/challenges/challenge-cowsay-two/solution2.js +++ b/challenges/challenge-cowsay-two/solution2.js @@ -1,18 +1,32 @@ -// ================= -// Stripped down cowsayer CLI, -// no libraries or arguments -// https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs -// ================= +const readline = require('readline'); -// 1. Make a command line interface. +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); -// 2. Make supplies for our speech bubble - -// 3. Make a cow that takes a string +function makeBubble(text) { + if (!text) text = "Moo!"; + const len = text.length; + const top = ' ' + '_'.repeat(len + 2); + const middle = `| ${text} |`; + const bottom = ' ' + '-'.repeat(len + 2); + return `${top}\n${middle}\n${bottom}`; +} const cow = (saying) => { - // how did you make the cow before? -} + const bubble = makeBubble(saying); + const asciiCow = ` + \\ ^__^ + \\ (oo)\\_______ + (__)\\ )\\/\\ + ||----w | + || || + `; + return bubble + asciiCow; +}; -// 4. Use readline to get a string from the terminal -// (with a prompt so it's clearer what we want) \ No newline at end of file +rl.question("What should the cow say? ", (answer) => { + console.log(cow(answer)); + rl.close(); +}); diff --git a/challenges/challenge-weather-app/app.js b/challenges/challenge-weather-app/app.js new file mode 100644 index 00000000..3c0cda9c --- /dev/null +++ b/challenges/challenge-weather-app/app.js @@ -0,0 +1,97 @@ +// ==================== +// Mini-weather App JS +// ==================== + +// Your working API keys +const WEATHER_API_KEY = "13940029dbb0ac27fa8e76f770798f71"; +const UNSPLASH_ACCESS_KEY = "1EkJLQ64exkT3BxWkvtunY6nGsyoUpmmVOIycUfobC4"; + +// DOM elements +const photoEl = document.getElementById("photo"); +const thumbsEl = document.getElementById("thumbs"); +const conditionsEl = document.getElementById("conditions"); +const creditUserEl = document.getElementById("credit-user"); +const searchForm = document.getElementById("search"); +const searchInput = document.getElementById("search-tf"); + +// Fetch weather data from OpenWeather +async function getWeather(city = "London") { + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${WEATHER_API_KEY}&units=metric`; + const res = await fetch(url); + if (!res.ok) throw new Error("Invalid API key or city"); + const data = await res.json(); + return data; +} + +// Fetch images from Unsplash +async function getImages(query) { + const url = `https://api.unsplash.com/search/photos?query=${query}&client_id=${UNSPLASH_ACCESS_KEY}&per_page=5`; + const res = await fetch(url); + const data = await res.json(); + return data.results; +} + +// Display main photo and thumbnails +function displayImages(images) { + if (!images.length) return; + + const mainImage = images[0]; + photoEl.style.backgroundImage = `url(${mainImage.urls.regular})`; + creditUserEl.textContent = mainImage.user.name; + creditUserEl.href = mainImage.user.links.html; + + thumbsEl.innerHTML = ""; + + images.forEach((img, index) => { + const thumb = document.createElement("div"); + thumb.classList.add("thumb"); + if (index === 0) thumb.classList.add("active"); + thumb.style.backgroundImage = `url(${img.urls.thumb})`; + thumb.dataset.full = img.urls.regular; + thumb.dataset.userName = img.user.name; + thumb.dataset.userLink = img.user.links.html; + + thumb.addEventListener("click", () => { + photoEl.style.backgroundImage = `url(${img.urls.regular})`; + creditUserEl.textContent = img.user.name; + creditUserEl.href = img.user.links.html; + + document.querySelectorAll(".thumb").forEach(t => t.classList.remove("active")); + thumb.classList.add("active"); + }); + + thumbsEl.appendChild(thumb); + }); +} + +// Display weather info +function displayWeather(weatherData) { + const description = weatherData.weather[0].description; + const temp = Math.round(weatherData.main.temp); + const cityName = weatherData.name; + conditionsEl.textContent = `${description}, ${temp}°C in ${cityName}`; +} + +// Update city +async function updateCity(city) { + try { + const weather = await getWeather(city); + displayWeather(weather); + const images = await getImages(weather.weather[0].description); + displayImages(images); + } catch (err) { + console.error(err); + conditionsEl.textContent = "Error fetching weather or images!"; + } +} + +// Load default city +updateCity("London"); + +// Handle search form +searchForm.addEventListener("submit", (e) => { + e.preventDefault(); + const city = searchInput.value.trim(); + if (city) updateCity(city); + searchInput.value = ""; +}); diff --git a/challenges/challenge-weather-app/index.html b/challenges/challenge-weather-app/index.html index b1add346..f25d1058 100644 --- a/challenges/challenge-weather-app/index.html +++ b/challenges/challenge-weather-app/index.html @@ -44,6 +44,7 @@