<repo_name>anamikapainuly/RetrofitAPI-Nav-Graph-Anamika-Test<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/ui/weather/future/detail/FutureDetailWeatherFragment.kt
package com.anupras.apl.anamika_test.ui.weather.future.detail

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.anupras.apl.anamika_test.R
import com.anupras.apl.anamika_test.constant.CITY_NAME
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import kotlinx.android.synthetic.main.future_detail_weather_fragment.*


class FutureDetailWeatherFragment : Fragment() {

    companion object {
        fun newInstance() =
            FutureDetailWeatherFragment()
    }

    private lateinit var viewModel: FutureDetailWeatherViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {


        return inflater.inflate(R.layout.future_detail_weather_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(FutureDetailWeatherViewModel::class.java)

        textView_city_name_detail.text = CITY_NAME

        date_to_show_detail.text = arguments?.getString("day")
        textView_condition_detail.text = arguments?.getString("description").toString().capitalize()
        textView_temperature_detail.text = arguments?.getString("temp")
        textView_min_max_temperature_detail.text = arguments?.getString("tempMinMax")


        val options: RequestOptions = RequestOptions()
            .centerCrop()
            .error(R.mipmap.ic_launcher_round)



        Glide .with(this)
              .load(arguments?.getString("icon").toString()).apply(options)
              .into(imageView_condition_icon_detail)




    }

}<file_sep>/app/build/generated/source/navigation-args/debug/com/anupras/apl/anamika_test/ui/weather/future/list/FutureListWeatherFragmentDirections.java
package com.anupras.apl.anamika_test.ui.weather.future.list;

import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.navigation.NavDirections;
import com.anupras.apl.anamika_test.R;
import java.lang.IllegalArgumentException;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
import java.util.HashMap;

public class FutureListWeatherFragmentDirections {
  private FutureListWeatherFragmentDirections() {
  }

  @NonNull
  public static ActionDetail actionDetail(@NonNull String day, @NonNull String description,
      @NonNull String temp, @NonNull String icon, @NonNull String tempMinMax) {
    return new ActionDetail(day, description, temp, icon, tempMinMax);
  }

  public static class ActionDetail implements NavDirections {
    private final HashMap arguments = new HashMap();

    private ActionDetail(@NonNull String day, @NonNull String description, @NonNull String temp,
        @NonNull String icon, @NonNull String tempMinMax) {
      if (day == null) {
        throw new IllegalArgumentException("Argument \"day\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("day", day);
      if (description == null) {
        throw new IllegalArgumentException("Argument \"description\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("description", description);
      if (temp == null) {
        throw new IllegalArgumentException("Argument \"temp\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("temp", temp);
      if (icon == null) {
        throw new IllegalArgumentException("Argument \"icon\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("icon", icon);
      if (tempMinMax == null) {
        throw new IllegalArgumentException("Argument \"tempMinMax\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("tempMinMax", tempMinMax);
    }

    @NonNull
    public ActionDetail setDay(@NonNull String day) {
      if (day == null) {
        throw new IllegalArgumentException("Argument \"day\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("day", day);
      return this;
    }

    @NonNull
    public ActionDetail setDescription(@NonNull String description) {
      if (description == null) {
        throw new IllegalArgumentException("Argument \"description\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("description", description);
      return this;
    }

    @NonNull
    public ActionDetail setTemp(@NonNull String temp) {
      if (temp == null) {
        throw new IllegalArgumentException("Argument \"temp\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("temp", temp);
      return this;
    }

    @NonNull
    public ActionDetail setIcon(@NonNull String icon) {
      if (icon == null) {
        throw new IllegalArgumentException("Argument \"icon\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("icon", icon);
      return this;
    }

    @NonNull
    public ActionDetail setTempMinMax(@NonNull String tempMinMax) {
      if (tempMinMax == null) {
        throw new IllegalArgumentException("Argument \"tempMinMax\" is marked as non-null but was passed a null value.");
      }
      this.arguments.put("tempMinMax", tempMinMax);
      return this;
    }

    @Override
    @SuppressWarnings("unchecked")
    @NonNull
    public Bundle getArguments() {
      Bundle __result = new Bundle();
      if (arguments.containsKey("day")) {
        String day = (String) arguments.get("day");
        __result.putString("day", day);
      }
      if (arguments.containsKey("description")) {
        String description = (String) arguments.get("description");
        __result.putString("description", description);
      }
      if (arguments.containsKey("temp")) {
        String temp = (String) arguments.get("temp");
        __result.putString("temp", temp);
      }
      if (arguments.containsKey("icon")) {
        String icon = (String) arguments.get("icon");
        __result.putString("icon", icon);
      }
      if (arguments.containsKey("tempMinMax")) {
        String tempMinMax = (String) arguments.get("tempMinMax");
        __result.putString("tempMinMax", tempMinMax);
      }
      return __result;
    }

    @Override
    public int getActionId() {
      return R.id.actionDetail;
    }

    @SuppressWarnings("unchecked")
    @NonNull
    public String getDay() {
      return (String) arguments.get("day");
    }

    @SuppressWarnings("unchecked")
    @NonNull
    public String getDescription() {
      return (String) arguments.get("description");
    }

    @SuppressWarnings("unchecked")
    @NonNull
    public String getTemp() {
      return (String) arguments.get("temp");
    }

    @SuppressWarnings("unchecked")
    @NonNull
    public String getIcon() {
      return (String) arguments.get("icon");
    }

    @SuppressWarnings("unchecked")
    @NonNull
    public String getTempMinMax() {
      return (String) arguments.get("tempMinMax");
    }

    @Override
    public boolean equals(Object object) {
      if (this == object) {
          return true;
      }
      if (object == null || getClass() != object.getClass()) {
          return false;
      }
      ActionDetail that = (ActionDetail) object;
      if (arguments.containsKey("day") != that.arguments.containsKey("day")) {
        return false;
      }
      if (getDay() != null ? !getDay().equals(that.getDay()) : that.getDay() != null) {
        return false;
      }
      if (arguments.containsKey("description") != that.arguments.containsKey("description")) {
        return false;
      }
      if (getDescription() != null ? !getDescription().equals(that.getDescription()) : that.getDescription() != null) {
        return false;
      }
      if (arguments.containsKey("temp") != that.arguments.containsKey("temp")) {
        return false;
      }
      if (getTemp() != null ? !getTemp().equals(that.getTemp()) : that.getTemp() != null) {
        return false;
      }
      if (arguments.containsKey("icon") != that.arguments.containsKey("icon")) {
        return false;
      }
      if (getIcon() != null ? !getIcon().equals(that.getIcon()) : that.getIcon() != null) {
        return false;
      }
      if (arguments.containsKey("tempMinMax") != that.arguments.containsKey("tempMinMax")) {
        return false;
      }
      if (getTempMinMax() != null ? !getTempMinMax().equals(that.getTempMinMax()) : that.getTempMinMax() != null) {
        return false;
      }
      if (getActionId() != that.getActionId()) {
        return false;
      }
      return true;
    }

    @Override
    public int hashCode() {
      int result = 1;
      result = 31 * result + (getDay() != null ? getDay().hashCode() : 0);
      result = 31 * result + (getDescription() != null ? getDescription().hashCode() : 0);
      result = 31 * result + (getTemp() != null ? getTemp().hashCode() : 0);
      result = 31 * result + (getIcon() != null ? getIcon().hashCode() : 0);
      result = 31 * result + (getTempMinMax() != null ? getTempMinMax().hashCode() : 0);
      result = 31 * result + getActionId();
      return result;
    }

    @Override
    public String toString() {
      return "ActionDetail(actionId=" + getActionId() + "){"
          + "day=" + getDay()
          + ", description=" + getDescription()
          + ", temp=" + getTemp()
          + ", icon=" + getIcon()
          + ", tempMinMax=" + getTempMinMax()
          + "}";
    }
  }
}
<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/ui/weather/future/list/FutureListWeatherFragment.kt
package com.anupras.apl.anamika_test.ui.weather.future.list

import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.anupras.apl.anamika_test.R
import com.anupras.apl.anamika_test.adapter.ForecastsWeatherAdapter
import com.anupras.apl.anamika_test.constant.CITY_NAME
import com.anupras.apl.anamika_test.constant.NO_OF_DAYS
import com.anupras.apl.anamika_test.constant.UNIT
import com.anupras.apl.anamika_test.data.ForecastDetail
import com.anupras.apl.anamika_test.service.OpenWeatherApiService
import kotlinx.android.synthetic.main.future_list_weather_fragment.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class FutureListWeatherFragment : Fragment() {

    companion object {
        fun newInstance() =
            FutureListWeatherFragment()
    }

    private lateinit var viewModel: FutureListWeatherViewModel

    protected lateinit var rootView: View
    lateinit var recyclerView: RecyclerView
    var dataList= ArrayList<ForecastDetail> ()
    var myAdapter: ForecastsWeatherAdapter? = null

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        rootView = inflater.inflate(R.layout.future_list_weather_fragment, container, false);
        initView()
        return rootView
    }

    private fun initView() {
        initializeRecyclerView()
    }

    //Initializing recycler view
    private fun initializeRecyclerView() {
        recyclerView = rootView.findViewById(R.id.recyclerView) as RecyclerView
        recyclerView.layoutManager = LinearLayoutManager(activity)
        //recyclerView.adapter = adapter
        myAdapter = activity?.let { ForecastsWeatherAdapter(dataList, it) }
        recyclerView.adapter = myAdapter
        myAdapter?.notifyDataSetChanged();

    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(FutureListWeatherViewModel::class.java)
        // TODO: Use the ViewModel


        val apiService = OpenWeatherApiService()

        GlobalScope.launch(Dispatchers.Main) {
            val futuretWeatherResponse =
                apiService.getFutureWeather(CITY_NAME, UNIT, NO_OF_DAYS).await()
            if (futuretWeatherResponse != null) {
                futuretWeatherResponse.forecast?.let { dataList.addAll(it)
                    recyclerView.adapter!!.notifyDataSetChanged()
                }
                Log.d("Response - DataList", "" + dataList)
            }
        }

    }

}<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/ui/weather/current/CurrentWeatherFragment.kt
package com.anupras.apl.anamika_test.ui.weather.current

import android.app.Activity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.anupras.apl.anamika_test.R
import com.anupras.apl.anamika_test.constant.CITY_NAME
import com.anupras.apl.anamika_test.constant.UNIT
import com.anupras.apl.anamika_test.service.OpenWeatherApiService
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.current_weather_fragment.*
import kotlinx.android.synthetic.main.current_weather_fragment.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*


class CurrentWeatherFragment : Fragment() {


    companion object {
        fun newInstance() =
            CurrentWeatherFragment()
    }

    private lateinit var viewModel: CurrentWeatherViewModel
    lateinit var cityText :String




    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view: View = inflater!!.inflate(R.layout.current_weather_fragment, container, false)



        //Button click to see weather of entered city
        view.search_btn_current.setOnClickListener { view ->

            //Hide Keyboard
            hideSoftKeyboard(activity!!)

            //Get city name from EditText
            var cityNameEntered = input_city_current.text.toString()

            if (cityNameEntered!=""){

                CITY_NAME=cityNameEntered
                loadApi(CITY_NAME)
            }
            textView_city_name_current.text= CITY_NAME
        }


        // Return the fragment view/layout
        return view
    }


    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(CurrentWeatherViewModel::class.java)
        //Load Data of default city
        loadApi(CITY_NAME)

       // val cityText= input_city_current.text.toString()

        // TODO: Use the ViewModel
    }

    fun hideSoftKeyboard(activity: Activity) {
        val inputMethodManager =
            activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        inputMethodManager.hideSoftInputFromWindow(activity.currentFocus!!.windowToken, 0)
    }

    private fun loadApi(CITY_NAME: String) {
        val apiService = OpenWeatherApiService()

        GlobalScope.launch(Dispatchers.Main) {
            val currentWeatherResponse = apiService.getCurrentWeather(CITY_NAME, UNIT).await()

            textView_temperature_current.text =
                currentWeatherResponse.currentWeatherEntry.temp.toString() + "°C"
            textView_min_max_temperature_current.text =
                "Min: " + currentWeatherResponse.currentWeatherEntry.tempMin.toString() + "°C" + "," + "Max: " + currentWeatherResponse.currentWeatherEntry.tempMax.toString() + "°C"

            //DESCRIPTION
            textView_condition_current.text= currentWeatherResponse.weather[0].description.capitalize()

            val dateReceived: Long = currentWeatherResponse.dt
            //val time = Date(date_received as Long * 1000)

            date_to_show_current.text= dateReceived?.let { getData(it) }
            textView_city_name_current.text=currentWeatherResponse.name

            Glide.with(this@CurrentWeatherFragment)
                .load("http://openweathermap.org/img/w/${currentWeatherResponse.weather[0].icon}.png")
                .into(imageView_condition_icon_current)

        }

    }

    private fun getData(dt: Long): String? {
        val timeFormatter = SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z")
        return timeFormatter.format(Date(dt * 1000L))
    }



}
<file_sep>/README.md

Use OpenWeatherMap.org to build a simple weather app that can show the weather for a city for the next 7 days.

Has the following features:
*Allow a user to enter a city name,
*App calls
*REST API which returns JSON for weather next for next 7 days.
*Display's day, temp, and description for each day using lists (recycle adapter)

*User can tap a day (or some other way) to see more detail for the current day, including: day, city, temp, min, max description and weather icon (optional).
*Navigation graph to navigate to a detail fragment showing more information
*Using OKHttp3 and Retrofit
*Kotin
*Nav Graph and fragments, only 1 activity

<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/data/FutureWeatherResponse.kt
package com.anupras.apl.anamika_test.data

import com.google.gson.annotations.SerializedName


data class FutureWeatherResponse (

    @SerializedName("list")
    val forecast : List<ForecastDetail> ? =  ArrayList(),

    @SerializedName("city") var city : City


)



data class ForecastDetail(
    @SerializedName("dt") var  date: Long?,
    @SerializedName("temp") var temperature : Temperature?,
    @SerializedName("weather") var description : List<WeatherDescription>,
    @SerializedName("pressure") var pressure : Double?,
    @SerializedName("humidity") var humidity :Double?)

data class City(
    @SerializedName("name") var cityName : String,
    @SerializedName("country") var country : String)

data class Temperature (
    @SerializedName("day") var dayTemperature: Double,
    @SerializedName("night") var nightTemperature: Double)

data class WeatherDescription(
    @SerializedName("main") var main : String,
    @SerializedName("description") var description: String,
    @SerializedName("icon") var icon: String)

<file_sep>/settings.gradle
include ':app'
rootProject.name = "anamika-test"<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/constant/const.kt
package com.anupras.apl.anamika_test.constant


//const val API_KEY = "<KEY>"
//const val API_KEY = "<KEY>"
var CITY_NAME : String = "Wellington"
const val UNIT = "metric";
const val NO_OF_DAYS = "7";<file_sep>/app/src/main/java/com/anupras/apl/anamika_test/adapter/ForecastsWeatherAdapter.kt
package com.anupras.apl.anamika_test.adapter

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.navigation.Navigation
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.anupras.apl.anamika_test.R
import com.anupras.apl.anamika_test.data.ForecastDetail
import com.anupras.apl.anamika_test.ui.weather.future.list.FutureListWeatherFragmentDirections
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.item_future_weather.view.*
import java.text.SimpleDateFormat
import java.util.*

class ForecastsWeatherAdapter(
    private val dataList: ArrayList<ForecastDetail>,
    private val context: Context
) : RecyclerView.Adapter<ForecastsWeatherAdapter.ForecastViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ForecastViewHolder {
        val rootView = LayoutInflater.from(parent.context).inflate(
            R.layout.item_future_weather,
            parent,
            false
        )
        return ForecastViewHolder(rootView)
    }

    override fun onBindViewHolder(holder: ForecastViewHolder, position: Int) {

        dataList[position].let {
            holder.bind(forecastElement = it)
        }
    }
    override fun getItemCount(): Int {
        return dataList.size
    }

        class ForecastViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bind(forecastElement: ForecastDetail) {

            val temMinMax: String="Day Temp: ${forecastElement.temperature?.dayTemperature}°C"+","+ " Night Temp: ${forecastElement.temperature?.nightTemperature}°C"
            val temperatureVar: String="${forecastElement.temperature?.dayTemperature} °C"
            val descriptionVar: String="${forecastElement.description[0].description}"
            val imageUrlVar: String="http://openweathermap.org/img/w/${forecastElement.description[0].icon}.png"
            val dateVar: String="${forecastElement.date?.let { getData(it)}}"

            itemView.setOnClickListener {
                Log.d("CHECK....", "position = " +   "${forecastElement.temperature?.dayTemperature} °C")
                showWeatherDetail(dateVar, descriptionVar,temperatureVar,imageUrlVar,temMinMax, itemView);

          }



            //Display temperature
            itemView.textView_temperature_future.text = temperatureVar

            //Display Date
            itemView.textView_date_future.text = "${forecastElement.date?.let { getDay(it)}}"

            //Display weather icon
                Glide.with(itemView.context)
                    .load(imageUrlVar)
                    .into(itemView.imageView_condition_icon_future)
            //Display condition
            itemView.textView_condition_future.text= descriptionVar.capitalize()


        }

        private fun showWeatherDetail(date:String, descriptionVar: String,temperatureVar: String,imageUrlVar: String,temMinMax: String, view: View) {
            val actionDetail = FutureListWeatherFragmentDirections.actionDetail(date, descriptionVar, temperatureVar, imageUrlVar, temMinMax)
            Navigation.findNavController(view).navigate(actionDetail)

        }

        private fun getData(dt: Long): String? {
            //val timeFormatter = SimpleDateFormat("\"dd-EEEE, MM, yyyy\"")
            val timeFormatter = SimpleDateFormat("E, dd MMM yyyy")
            return timeFormatter.format(Date(dt * 1000L))
        }

            private fun getDay(dt: Long): String? {
                //val timeFormatter = SimpleDateFormat("\"dd-EEEE, MM, yyyy\"")
                val timeFormatter = SimpleDateFormat("EEEE")
                return timeFormatter.format(Date(dt * 1000L))
            }


    }

}
