Currency_app.js code

        
import { CURRENCY_CODES } from './currency_app_codes.js'
import { formatNumber, toNumber } from './utils/formatNumber.js'

const header = document.querySelector('header')
const inputField = document.querySelectorAll('input')
const currencyCode = document.querySelectorAll('[data-currency-code]')
const countryFlag = document.querySelectorAll('[data-country-flag]')
const errorMessage = document.querySelector('#error')
const gettinDataMessage = document.querySelector('#getting_data')
const button = document.querySelectorAll('[data-popup-button]')
const popupList = [...document.querySelectorAll('[data-popup-list]')]
let exchangeRate = 1

const URL = 'https://api.fxratesapi.com'
const options = {
  currencies: 'USD,EUR,RUB,TRY,KZT,CAD,GBP,CHF',
  format: 'json',
}
const optionsTimeseries = {
  currencies: 'USD,EUR,RUB,TRY,KZT,CAD,GBP,CHF',
  base: 'EUR',
  format: 'json',
}

let currencyRatesToday, currencyRatesForYear

// 1. Set default currencies and the base in options
let currencyOne = 'USD'
let currencyTwo = 'RUB'
setCurrencies(currencyOne, currencyTwo)

// 2. We download data from the server and write it to objects:
// currencyRatesToday и currencyRatesForYear

currencyRatesToday = await getCurrencyToday(options)
currencyRatesForYear = await getCurrencyForYear(optionsTimeseries)

// Rotate an object by date from lowest to highest
currencyRatesForYear = Object.keys({ ...currencyRatesForYear })
  .sort()
  .reduce((sortedArray, date) => {
    sortedArray[date] = currencyRatesForYear[date]
    return sortedArray
  }, {})

const currencyDatesForYear = Object.values(currencyRatesForYear)

// 3. We set exchange rates depending on the selected currencies
// setCurrencyRate()

setCurrencyRate()

// 4. Exchange rate chart for default USD and RUB
let currencyChart
drawChart()

inputField[0].addEventListener('input', setNumberInputField1)
inputField[1].addEventListener('input', setNumberInputField0)

button[0].addEventListener('click', () => {
  popupList[1].classList.add('hiding')
  popupList[0].classList.toggle('hiding')
  addOrRemoveOverlay()
})
button[1].addEventListener('click', e => {
  popupList[0].classList.add('hiding')
  popupList[1].classList.toggle('hiding')
  addOrRemoveOverlay()
})

// Closing an overlay
document.addEventListener('click', e => {
  if (e.target.matches('[data-new-overlay]')) closeAllPopupsAndOverlay()
})

// Changing currencies
popupList[0].addEventListener('click', e => {
  const isClickedLi = e.target.closest('li')
  if (isClickedLi) {
    currencyOne = isClickedLi.dataset.currency
    setCurrencies(currencyOne, currencyTwo)
    setCurrencyRate()
    setNumberInputField1()
    updateValuesForChart()
    currencyChart.update()
  }
})

popupList[1].addEventListener('click', e => {
  const isClickedLi = e.target.closest('li')
  if (isClickedLi) {
    currencyTwo = isClickedLi.dataset.currency
    setCurrencies(currencyOne, currencyTwo)
    setCurrencyRate()
    setNumberInputField0()
    updateValuesForChart()
    currencyChart.update()
  }
})

// ----- Additional functions -----

function drawChart() {
  const daysUnformatted = Object.keys(currencyRatesForYear)
  const days = daysUnformatted.map(formatDate)
  const rates = setValuesForChart()

  const ctx = document.getElementById('annual_course')

  Chart.defaults.font.size = 18
  Chart.defaults.color = '#ccced0'

  const data = {
    labels: days,
    datasets: [
      {
        label: `Rate ${currencyOne} / ${currencyTwo}`,
        data: rates,
        backgroundColor: 'rgba(245, 192, 41, 0.3)',
        borderColor: '#f5c029',
        borderWidth: 1,
        fill: true,
      },
    ],
  }

  const options = {
    scales: {
      y: {
        beginAtZero: false,
      },
      x: {
        ticks: {
          callback: function (value, index, values) {
            if (index % 45 === 0 || index === data.length - 1)
              return data.labels[index]
          },
        },
      },
    },
    plugins: {
      legend: {
        display: false,
      },
      tooltip: {
        enabled: true,
        intersect: false,
        displayColors: false,
        padding: 12,
      },
    },
  }

  currencyChart = new Chart(ctx, {
    type: 'line',
    data,
    options,
  })
}

function updateValuesForChart() {
  currencyChart.data.datasets[0].data = setValuesForChart()
  currencyChart.data.datasets[0].label = `Rate ${currencyOne} / ${currencyTwo}`
}

function setValuesForChart() {
  return currencyDatesForYear.map(dailyRate => {
    return (dailyRate[currencyTwo] / dailyRate[currencyOne]).toFixed(2)
  })
}

function formatDate(dayUnformatted) {
  return new Intl.DateTimeFormat().format(Date.parse(dayUnformatted))
}

function setCurrencies(currencyOne, currencyTwo) {
  options.base = currencyOne
  currencyCode[0].dataset.currencyCode = currencyOne
  currencyCode[1].dataset.currencyCode = currencyTwo
  currencyCode[0].textContent = currencyOne
  currencyCode[1].textContent = currencyTwo
  countryFlag[0].src = `images/svg/${CURRENCY_CODES[currencyOne]}`
  countryFlag[1].src = `images/svg/${CURRENCY_CODES[currencyTwo]}`
}

function setCurrencyRate() {
  exchangeRate =
    currencyRatesToday[currencyTwo] / currencyRatesToday[currencyOne]
}

function setNumberInputField1() {
  inputField[1].value = formatNumber(
    toNumber(inputField[0].value) * exchangeRate
  )
}

function setNumberInputField0() {
  inputField[0].value = formatNumber(
    toNumber(inputField[1].value) / exchangeRate
  )
}

// Getting exchange rates for today
async function getCurrencyToday(options) {
  gettinDataMessage.classList.remove('hiding')

  const url = `${URL}/latest?${params(options)}`
  console.log('url на тудей', url)

  const currencyRates = await (await fetch(url).catch(handleError)).json()

  gettinDataMessage.classList.add('hiding')
  if (currencyRates.code === 400 || currencyRates.success === false) {
    errorMessage.classList.remove('hiding')
    console.log('Error from getCurrencyToday')

    const localUrl = 'JS/currency_latest.json'
    const savedCurrencyRates = await (await fetch(localUrl)).json()
    return savedCurrencyRates.rates
  }
  return currencyRates.rates
}

// Receive courses from the past year
async function getCurrencyForYear(options) {
  gettinDataMessage.classList.remove('hiding')

  const { startDate, endDate } = datesForDisplayCurrency()
  const url = `${URL}/timeseries?start_date=${startDate}&end_date=${endDate}&${params(
    options
  )}`

  console.log('url на год', url)

  const responseFromServer = await fetch(url).catch(handleError)
  const currencyRates = await responseFromServer.json()

  gettinDataMessage.classList.add('hiding')
  if (currencyRates.code === 400 || currencyRates.success === false) {
    errorMessage.classList.remove('hiding')
    console.log('Error from getCurrencyForYear')

    const localUrl = 'JS/currency_timeseries.json'
    const savedCurrencyRates = await (await fetch(localUrl)).json()
    return savedCurrencyRates.rates
  }
  return currencyRates.rates
}

function datesForDisplayCurrency() {
  const dateNow = new Date()

  let date = dateNow.getUTCDate()
  let month = dateNow.getUTCMonth() + 1
  const year = dateNow.getUTCFullYear()

  if (date.toString().length === 1) date = '0' + date
  if (month.toString().length === 1) month = '0' + month
  return {
    startDate: `${year - 1}-${month}-${date}`,
    endDate: `${year}-${month}-${date}`,
  }
}

function params(options) {
  return new URLSearchParams({
    ...options,
  })
}

function handleError() {
  const resp = new Response(
    JSON.stringify({
      code: 400,
    })
  )
  return resp
}

function addOrRemoveOverlay() {
  if (popupList.every(list => list.classList.contains('hiding'))) {
    header.removeAttribute('data-new-overlay')
  } else {
    header.setAttribute('data-new-overlay', true)
  }
}

function closeAllPopupsAndOverlay() {
  popupList[0].classList.add('hiding')
  popupList[1].classList.add('hiding')
  header.removeAttribute('data-new-overlay')
}