diff --git a/fullstack/task/packages/server/src/entities/exchange-rate.model.ts b/fullstack/task/packages/server/src/entities/exchange-rate.model.ts index 170814a..043d2db 100644 --- a/fullstack/task/packages/server/src/entities/exchange-rate.model.ts +++ b/fullstack/task/packages/server/src/entities/exchange-rate.model.ts @@ -6,11 +6,14 @@ export class ExchangeRate { public country!: string; @Field(() => String) - public currncy!: string; + public currency!: string; @Field(() => Number) public amount!: number; @Field(() => String) public code!: string; + + @Field(() => Number) + public rate!: number; } diff --git a/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.resolver.ts b/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.resolver.ts index 54f79dd..69428e8 100644 --- a/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.resolver.ts +++ b/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.resolver.ts @@ -6,9 +6,9 @@ import { ExchangeRateService } from './exchange-rate.service'; export class ExchangeRateResolver { constructor(private readonly exchangeRateService: ExchangeRateService) {} - // TODO: Implement a GraphQL Query that returns the exchange rates - @Query(() => String) - async exchangeRates(): Promise { - return 'Hello'; + @Query(() => [ExchangeRate]) + async exchangeRates(): Promise { + const rates: ExchangeRate[] = await this.exchangeRateService.getExchangeRates(); + return rates; } } diff --git a/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.service.ts b/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.service.ts index d19b932..dbd620c 100644 --- a/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.service.ts +++ b/fullstack/task/packages/server/src/entity-modules/exchange-rate/exchange-rate.service.ts @@ -1,13 +1,33 @@ import { Injectable } from '@nestjs/common'; import { ExchangeRate } from '@cuid/entities'; +import fetch from 'node-fetch'; + +const CNB_URL = 'https://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt'; @Injectable() export class ExchangeRateService { public getExchangeRates = async () => { const rates: ExchangeRate[] = []; - // TODO: Implement the fetching and parsing of the exchange rates. - // Use this method in the resolver. + // Fetch the exchange rates from CNB website + const response: Response = await fetch(CNB_URL); + const data: string = await response.text(); + + // Split the data into lines and remove header + const rateLines: string[] = data.trim().split('\n').splice(2); + + // Loop through each line and push a new object to the array (wanted to use map, but since rates is a const, I use loop with Array.push instead) + for (const rateLine of rateLines) { + const [country, currency, amount, code, rate] = rateLine.split('|'); + const currencyObject: ExchangeRate = { + country, + currency, + amount: parseInt(amount), + code, + rate: parseFloat(rate.replace(',', '.')), + }; + rates.push(currencyObject); + } return rates; }; diff --git a/fullstack/task/packages/web/src/App.tsx b/fullstack/task/packages/web/src/App.tsx index f5f039e..6438cc7 100644 --- a/fullstack/task/packages/web/src/App.tsx +++ b/fullstack/task/packages/web/src/App.tsx @@ -1,9 +1,30 @@ +import { useQuery, gql } from '@apollo/client'; +import ExchangeRateTable from './ExchangeRateTable'; + +const EXCHANGE_RATES = gql` + query GetExchangeRates { + exchangeRates { + country + currency + amount + code + rate + } + } +`; + function App() { - // TODO: Add the FE for exchange rates here. + const { loading, error, data } = useQuery(EXCHANGE_RATES); + + if (loading) return

Loading...

; + if (error) return

Error: {error.message}

; + + const exchangeRatesData = data.exchangeRates; return (
-

Add the exchange rates here

+

Exchange Rates

+
); } diff --git a/fullstack/task/packages/web/src/ExchangeRateTable.tsx b/fullstack/task/packages/web/src/ExchangeRateTable.tsx new file mode 100644 index 0000000..d579841 --- /dev/null +++ b/fullstack/task/packages/web/src/ExchangeRateTable.tsx @@ -0,0 +1,58 @@ +interface ExchangeRate { + country: string; + currency: string; + amount: number; + code: string; + rate: number; +} + +interface ExchangeRateTableProps { + data: ExchangeRate[]; +} + +const ExchangeRateTable: React.FC = ({ data }) => { + return ( + + + + + + + + + + + + {data.map((row, index) => ( + + + + + + + + ))} + +
CountryCurrencyAmountCodeRate
{row.country}{row.currency}{row.amount}{row.code}{row.rate}
+ ); +}; + +const tableHeaderStyle: React.CSSProperties = { + borderBottom: '2px solid #ccc', + padding: '8px', + textAlign: "left", + }; + + const evenRowStyle: React.CSSProperties = { + backgroundColor: '#f2f2f2', + }; + + const oddRowStyle: React.CSSProperties = { + backgroundColor: '#ffffff', + }; + + const tableCellStyle: React.CSSProperties = { + padding: '8px', + }; + +export default ExchangeRateTable;