diff --git a/weather/src/components/weather.js b/weather/src/components/weather.js index 816478c..81dc560 100644 --- a/weather/src/components/weather.js +++ b/weather/src/components/weather.js @@ -1,4 +1,4 @@ -class WeatherComponent { +export default class WeatherComponent { constructor(apiKey) { this.apiKey = apiKey; } @@ -84,13 +84,13 @@ class WeatherComponent { } } -const api = 'bd5d23eea5751c12b0ef75344e3df932'; - -const weather = new WeatherComponent(api); -weather.getWeather(20716).then((data) => console.log(data)); -weather.getWeather(22030).then((data) => { - data.convertTemp('C'); - console.log(data); - data.convertTemp('F'); - console.log(data); -}); +// const api = 'bd5d23eea5751c12b0ef75344e3df932'; +// +// const weather = new WeatherComponent(api); +// weather.getWeather(20716).then((data) => console.log(data)); +// weather.getWeather(22030).then((data) => { +// data.convertTemp('C'); +// console.log(data); +// data.convertTemp('F'); +// console.log(data); +// }); diff --git a/weather/src/components/website.js b/weather/src/components/website.js new file mode 100644 index 0000000..dd67ded --- /dev/null +++ b/weather/src/components/website.js @@ -0,0 +1,223 @@ +import WeatherComponent from './weather'; + +class MainWebsite { + constructor(apikey) { + this.weatherComponent = new WeatherComponent(apikey); + + this.container = document.createElement('div'); + this.form = document.createElement('form'); + } + + websiteStructure() { + this.container.classList.add('container'); + this.formStructure(); + this.weatherComponentStructure(); + + const title = document.createElement('h1'); + title.classList.add('title'); + title.textContent = 'Weather'; + + // Add form to container + this.container.append(title, this.weatherDiv); + + return this.container; + } + + weatherComponentStructure() { + // Main weather info component + this.weatherDiv = document.createElement('div'); + this.weatherDiv.classList.add('weather-container'); + + // Related to fetched weather report + this.reportDiv = document.createElement('div'); + this.reportStructure(); + this.reportTempDetails.append( + this.reportTempFeelsLike, + this.reportMinTemp, + this.reportMaxTemp, + ); + this.reportDiv.append( + this.reportCity, + // this.reportConditions, + this.reportConditionDescription, + this.reportTemp, + this.reportTime, + this.reportTempDetails, + ); + + this.weatherDiv.append(this.form, this.reportDiv); + } + + reportStructure() { + this.reportDiv.classList.add('report-container'); + + this.reportCity = document.createElement('h2'); + this.reportCity.classList.add('city'); + + this.reportTemp = document.createElement('span'); + this.reportTemp.classList.add('temp'); + + this.reportTime = document.createElement('span'); + this.reportTime.classList.add('time'); + + this.reportTempDetails = document.createElement('div'); + this.reportTempDetails.classList.add('temp-details-container'); + + this.reportTempFeelsLike = document.createElement('span'); + this.reportTempFeelsLike.classList.add('feels-like'); + + this.reportMaxTemp = document.createElement('span'); + this.reportMaxTemp.classList.add('max'); + + this.reportMinTemp = document.createElement('span'); + this.reportMinTemp.classList.add('min'); + + // this.reportConditions = document.createElement('span'); + // this.reportConditions.classList.add('conditions'); + + this.reportConditionDescription = document.createElement('span'); + this.reportConditionDescription.classList.add('conditions-desc'); + } + + updateReportComponents() { + const items = [ + this.reportTime, + this.reportCity, + this.reportTemp, + this.reportMaxTemp, + this.reportMinTemp, + this.reportConditionDescription, + // this.reportConditions, + ]; + + function clearValues() { + items.forEach((e) => { + e.textContent = ''; + }); + } + + function updateReportTemperatureText(item, temp, range) { + item.textContent = `${range}: ${temp}°`; + } + + function updateReportText(item, text) { + item.textContent = `${text}`; + } + + return { clearValues, updateReportTemperatureText, updateReportText }; + } + + formStructure() { + const div = document.createElement('div'); + div.classList.add('form-input'); + + this.form.classList.add('form'); + this.form.method = 'post'; + this.form.action = '#'; + + const input = document.createElement('input'); + input.id = 'zipcode'; + input.name = 'zipcode'; + input.type = 'text'; + input.placeholder = 'Zipcode'; + input.required = true; + input.addEventListener('input', (input) => + this.formInputValidationChecker(input.target), + ); + + const span = document.createElement('span'); + span.classList.add('zipcode-span'); + + this.button = document.createElement('button'); + this.button.type = 'submit'; + this.button.classList.add('btn'); + this.button.textContent = 'Submit'; + this.button.addEventListener('click', (e) => this.handleSubmit(e)); + + div.append(input, span); + this.form.append(div, this.button); + } + + formInputValidationChecker(e) { + this.ensureValidZipCode(e); + } + + handleSubmit(e) { + e.preventDefault(); + if (this.validZipcode) { + const input = document.querySelector('#zipcode'); + // this.updateWeatherComponent({ temp: { current: 98 } }); + this.weatherComponent + .getWeather(input.value) + .then((report) => this.updateWeatherComponent(report)); + input.value = ''; + } + } + + ensureValidZipCode(zipcode) { + const validityMessage = 'Please enter a 5 digit zip code!'; + + zipcode.minLength = 5; + zipcode.maxLength = 5; + zipcode.pattern = '\\d{5}'; + + if ( + zipcode.validity.tooShort || + zipcode.validity.patternMismatch || + zipcode.validity.tooLong + ) { + zipcode.setCustomValidity(validityMessage); + zipcode.nextSibling.textContent = validityMessage; + this.validZipcode = false; + } else { + zipcode.setCustomValidity(''); + zipcode.nextSibling.textContent = ''; + this.validZipcode = true; + } + } + + updateWeatherComponent(weatherReportData) { + // clear the values in the dom + const reportUpdater = this.updateReportComponents(); + reportUpdater.clearValues(); + + // convert the F and C temps + weatherReportData.convertTemp('C'); + weatherReportData.convertTemp('F'); + console.table(weatherReportData); + + reportUpdater.updateReportText(this.reportCity, weatherReportData.city); + reportUpdater.updateReportText( + this.reportTemp, + weatherReportData.F.current, + ); + + // reportUpdater.updateReportText( + // this.reportConditions, + // weatherReportData.weather.main, + // ); + reportUpdater.updateReportText( + this.reportConditionDescription, + weatherReportData.weather.description, + ); + + reportUpdater.updateReportTemperatureText( + this.reportTempFeelsLike, + weatherReportData.F.feelsLike, + 'Feels like', + ); + + reportUpdater.updateReportTemperatureText( + this.reportMaxTemp, + weatherReportData.F.maxTemp, + 'max', + ); + reportUpdater.updateReportTemperatureText( + this.reportMinTemp, + weatherReportData.F.minTemp, + 'min', + ); + } +} + +export { MainWebsite }; diff --git a/weather/src/index.js b/weather/src/index.js index e69de29..85f4bf3 100644 --- a/weather/src/index.js +++ b/weather/src/index.js @@ -0,0 +1,28 @@ +import { MainWebsite } from './components/website'; +import './style.css'; + +const api = 'bd5d23eea5751c12b0ef75344e3df932'; +const web = new MainWebsite(api); + +function fonts() { + let fontLink = document.createElement('link'); + fontLink.rel = 'preconnect'; + fontLink.href = 'https://fonts.googleapis.com'; + + let fontLinkTwo = document.createElement('link'); + fontLinkTwo.rel = 'preconnect'; + fontLinkTwo.href = 'https://fonts.gstatic.com'; + fontLinkTwo.crossOrigin = true; + + let style = document.createElement('link'); + style.rel = 'stylesheet'; + style.href = + 'https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap'; + + document.head.appendChild(fontLink); + document.head.appendChild(fontLinkTwo); + document.head.appendChild(style); +} + +fonts(); +document.body.appendChild(web.websiteStructure()); diff --git a/weather/src/style.css b/weather/src/style.css index e69de29..19f123f 100644 --- a/weather/src/style.css +++ b/weather/src/style.css @@ -0,0 +1,95 @@ +:root { + --dark-color: #000; + --font-size: 18px; +} + +html, +body { + padding: 0; + margin: 0; + font-size: var(--font-size); + font-family: 'Inter', sans-serif; + font-optical-sizing: auto; + font-weight: ; + font-style: normal; + font-variation-settings: 'slnt' 0; +} + +.title { + font-size: 3rem; + font-weight: 800; + text-align: center; + margin: 0; +} + +.form { + display: flex; + gap: 10px; + padding: 20px; + margin: auto; +} + +.form-input { + display: flex; + flex-direction: column; + margin: auto; +} + +.form button { + align-self: baseline; + flex: 1; + height: 41px; +} + +.form-input input { + padding: 10px; + font-size: 1rem; + margin-bottom: 5px; +} + +.form-input span { + color: red; + margin-left: 5px; +} + +.form-input span { + font-size: 0.8rem; +} + +.weather-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.report-container { + display: grid; + grid-template-columns: repeat(3, 1fr); +} + +.city { + grid-column: 1 / span 3; + place-self: center; +} + +.temp { + grid-column: 1 / span 1; + grid-row: 2 / span 1; + font-size: 4rem; + font-weight: 900; +} + +/* .conditions { */ +/* grid-column: 3 / span 1; */ +/* grid-row: 2 / span 1; */ +/* } */ +.conditions-desc { + grid-column: 3 / span 1; + grid-row: 3 / span 1; +} + +.temp-details-container { + grid-row: 3 / span 1; + display: flex; + flex-direction: column; +}