Angular: Weather Finder

Create a Weather Finder component, as shown below:

The component must have the following functionalities:

  • The input should initially be empty. The user can type a city name into this input box to search for weather details for this city.
  • Clicking on the ‘Search’ button should make an API GET call to the URL ‘https://jsonmock.hackerrank.com/api/weather?name=<name>’ using the Angular HttpClient module. Here, <name> is the city name entered into the text box. For example, for the value ‘Dallas’, the API request is https://jsonmock.hackerrank.com/api/weather?name=Dallas. There will be data for the cities ‘Dallas’ and ‘Oakland’.
  • The response contains a data field, where data is an array of objects, and each object is a weather record. Only the first record of the array is rendered in this component. A sample data field for ‘Dallas’ is below:”data”: [ { “name”: “Dallas”, “weather”: “12 degree”, // Format is always “<value> degree” “status”: [ “Wind: 2Kmph”, // String “Humidity: 5%” // String ] } ]
  • The weather details should be rendered inside <div data-test-id=”weather-details”></div> . This div should not be rendered initially since no API has been hit yet.
  • Each weather record contains a weather field. Retrieve the value and display it in the <span data-test-id=”result-temperature”></span> element.
  • If the value in the weather field is less than 20, render the cold weather icon by rendering <i data-test-id=”icon-cold”></i>. If the value is greater than or equal to 20, render the sunny weather icon by rendering <i data-test-id=”icon-sunny”></i>.
  • Each weather record contains a status field which is an array of strings.
  • The first string denotes the wind value and the second string denotes the humidity value.
    • Render the wind value in <div data-test-id=”result-wind”></div>. 
    • Render the humidity value in <div data-test-id=”result-humidity”></div>. 
  • If no records are returned for any city, render <div data-test-id=”no-result”>No Results Found</div> instead.  This element must be visible only when the data field is an empty array. This div should not be rendered initially since no API has been hit yet.
  • Please note that the input field accepts only text. Test cases take will only call the API with valid input, so input validation is not required.
  • For testing purposes, please use the following cities and their corresponding weather conditions:Dallas – Cold Oakland – Sunny 

The following data-test-id attributes are required in the component for the tests to pass:

  • The input: ‘app-input’
  • The ‘Search’ button: ‘submit-button’
  • The weather details: ‘weather-details’
  • The sunny icon: ‘icon-sunny’
  • The cold icon: ‘icon-cold’
  • The span showing temperature: ‘result-temperature’
  • The div showing wind information: ‘result-wind’
  • The div showing wind information: ‘result-humidity’
  • The ‘No Results Found’ div: ‘no-result’

Please note that the component has the listed data-test-id attributes for test cases and certain classes and ids for rendering purposes. They should not be changed.

SOLUTIONS:

				
					//weatherFinder.component.ts
import {Component, OnInit, Input} from '@angular/core';
import { HttpClient } from "@angular/common/http";
interface CityWeather {
  name: string;
  weather: string;
  status: string[];
}

interface ApiResponse {
  page: number;
  per_page: number;
  total: number;
  total_pages: number;
  data: CityWeather[];
}
interface data{
    name :String
    temprature :String
    wind :String
    humidity :String
  }
@Component({
  selector: 'weather-finder',
  templateUrl: './weatherFinder.component.html',
  styleUrls: ['./weatherFinder.component.scss']
})
export class WeatherFinder implements OnInit {
  constructor (private http :HttpClient){}
@Input() weatherData :data[];
city :any

cityDetails ={
  data:[],
  iconSunny :false ,
  iconCold:false,
  weather : null
}
showNoResult :boolean = false
hideDetails :boolean =false


cityChange(){
  let value = this.city
  if(value){

    this.http.get('https://jsonmock.hackerrank.com/api/weather?name='+value).subscribe((res :any)=>{
     this.cityDetails.data = res.data;


    if(this.cityDetails.data.length == 0){
      this.showNoResult = true
      this.hideDetails = false
    }else{
      this.showNoResult = false
      this.cityDetails.weather = res.data[0].weather
      let t = res.data[0].weather;
      let m =  t.split(' ')

      if(m[0] <20){
        this.hideDetails  =true
        this.cityDetails.iconCold = true;
        this.cityDetails.iconSunny = false;
      }else if(m[0] >19 ){
        this.hideDetails = true
        this.cityDetails.iconSunny = true;
        this.cityDetails.iconCold = false;
      }
    }

    })


  }
}
  ngOnInit(): void {
  }


}

				
			
				
					//app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'Weather Finder';
}

				
			
				
					/* weatherFinder.component.html */
<div class="weather-data layout-column align-items-center mt-50">
  <section class="layout-row align-items-center justify-content-center">
      <input type="text" [(ngModel)]="city"  class="large ml-30" placeholder="Dallas" data-test-id="app-input"/>
      <button (click)="cityChange()" data-test-id="submit-button">Search</button>
  </section>

  <section class="mt-20 layout-row align-items-center justify-content-center">
    <div class="card outlined">
        <div *ngIf="hideDetails" data-test-id="weather-details" class="card-text pt-10 layout-row justify-content-between">
            <div class="mt-20 outlined">
              <i *ngIf="cityDetails.iconSunny" data-test-id="icon-sunny" class="material-icons">wb_sunny</i>
              <i *ngIf="cityDetails.iconCold" data-test-id="icon-cold" class="material-icons">ac_unit</i>
              <span data-test-id="result-temperature" class="temperature">{{cityDetails.weather}}</span>
            </div>
            <div class="mr-15 mb-15">
              <div data-test-id="result-wind" class="mt-20">
                {{cityDetails.data[0].status[0]}}
              </div>
              <div data-test-id="result-humidity" class="mt-20">
                {{cityDetails.data[0].status[1]}}
              </div>
            </div>
        </div>
        <div *ngIf="showNoResult" data-test-id="no-result" class="layout-row justify-content-center align-items-center card-text" >No Results Found</div>
    </div>
  </section>
</div>