Skip to content

Commit e5e43a5

Browse files
authored
Feature: currency rates (#170)
* Currency feature
1 parent 152140e commit e5e43a5

File tree

6 files changed

+164
-1
lines changed

6 files changed

+164
-1
lines changed

app/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from app.dependencies import (logger, MEDIA_PATH, STATIC_PATH, templates)
99
from app.internal import daily_quotes, json_data_loader
1010
from app.routers import (
11-
agenda, calendar, categories, dayview, email,
11+
agenda, calendar, categories, currency, dayview, email,
1212
event, invitation, profile, search, telegram, whatsapp
1313
)
1414
from app.telegram.bot import telegram_bot
@@ -38,6 +38,7 @@ def create_tables(engine, psql_environment):
3838
agenda.router,
3939
calendar.router,
4040
categories.router,
41+
currency.router,
4142
dayview.router,
4243
email.router,
4344
event.router,

app/routers/currency.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import datetime
2+
3+
from app.dependencies import templates
4+
from fastapi import APIRouter, Request
5+
6+
7+
router = APIRouter()
8+
9+
# TODO: Add this as a feature to the calendar view/
10+
# day view/features panel frontend
11+
12+
13+
@router.get("/currency")
14+
def today_currency(request: Request):
15+
"""Current day currency router"""
16+
17+
date = datetime.date.today().strftime("%Y-%m-%d")
18+
return currency(request, date)
19+
20+
21+
@router.get("/currency/{date}")
22+
def currency(request: Request, date: str):
23+
"""Custom date currency router"""
24+
25+
# TODO: get user default/preferred currency
26+
base = "USD"
27+
28+
return templates.TemplateResponse("currency.html", {
29+
"request": request,
30+
"base": base,
31+
"date": date
32+
})

app/static/currency.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
div[data-visible='0'] {
2+
display: none;
3+
}
4+
div[data-visible='1'] {
5+
display: block;
6+
}

app/static/currency.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
function getCurrency(baseCurrency, dateToday) {
2+
const showCurrencyElement = document.getElementById("showCurrency")
3+
const currencyViewElement = document.getElementById("currencyView");
4+
const myUrl = 'https://api.exchangeratesapi.io/' + dateToday + '?base=' + baseCurrency
5+
6+
async function getResponse(myUrl) {
7+
let response = await fetch(myUrl);
8+
if (response.ok) {
9+
let result = await response.json();
10+
currencyViewElement.innerHTML = "";
11+
showCurrencyElement.dataset.visible = "1";
12+
return result;
13+
}
14+
}
15+
16+
getResponse(myUrl)
17+
.then(result => buildCurrencyList(result));
18+
19+
function buildCurrencyList(data) {
20+
function getListItem() {
21+
const listItem = document.createElement("li");
22+
listItem.className = "list-group-item title_size_small";
23+
return listItem;
24+
}
25+
26+
function createBoldListItem(fieldString, currViewElem) {
27+
const listItem = getListItem();
28+
const boldItem = document.createElement("strong");
29+
boldItem.innerHTML = fieldString;
30+
listItem.appendChild(boldItem);
31+
currViewElem.appendChild(listItem);
32+
}
33+
34+
function getAnchorItem() {
35+
const linkItem = document.createElement("a");
36+
linkItem.setAttribute("href", "javascript:void(0)");
37+
linkItem.setAttribute("id", key);
38+
linkItem.innerText = key;
39+
return linkItem;
40+
}
41+
42+
function getRatesItem(fieldString) {
43+
let ratesItem = document.createElement("div");
44+
ratesItem.setAttribute("style", "display: inline;")
45+
ratesItem.innerHTML = fieldString;
46+
return ratesItem;
47+
}
48+
49+
function createAllElements(dataRates, baseCurr, currViewElem) {
50+
for (key in dataRates) {
51+
if (key !== baseCurr) {
52+
let listItem = getListItem();
53+
let linkItem = getAnchorItem();
54+
let ratesItem = getRatesItem(": " + dataRates[key]);
55+
listItem.appendChild(linkItem);
56+
listItem.appendChild(ratesItem);
57+
currViewElem.appendChild(listItem);
58+
}
59+
}
60+
}
61+
62+
// Create Base currency list item
63+
createBoldListItem("BASE: " + baseCurrency, currencyViewElement);
64+
// Create all rates list items
65+
createAllElements(data.rates, baseCurrency, currencyViewElement);
66+
// Create date list item
67+
createBoldListItem(dateToday, currencyViewElement);
68+
69+
return true;
70+
}
71+
}

app/templates/currency.html

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
8+
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
9+
<link rel="stylesheet" href="{{ url_for('static', path='/currency.css') }}">
10+
<title>currency</title>
11+
</head>
12+
13+
<body>
14+
<div id="showCurrency" data-visible="0">
15+
<p style="margin: 1rem;">
16+
<button class="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#collapseExample"
17+
aria-expanded="false" aria-controls="collapseExample">
18+
Currency</button>
19+
<div class="row" style="margin: 1rem; width: 14rem;">
20+
<div class="col">
21+
<div class="collapse multi-collapse" id="collapseExample">
22+
<ul class="list-group list-group-flush" id="currencyView">
23+
<!-- JS currency content -->
24+
</ul>
25+
</div>
26+
</div>
27+
</div>
28+
</div>
29+
<script type="text/javascript" src="{{ url_for('static', path='/currency.js')}}"></script>
30+
<script type="text/javascript">
31+
getCurrency("{{ base | safe }}", "{{ date | safe }}");
32+
document.getElementById("currencyView").addEventListener("click", function (e) {
33+
if (e.target && e.target.nodeName == "A") {
34+
getCurrency(e.target.id, "{{ date | safe }}");
35+
}
36+
}, false);
37+
</script>
38+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
39+
integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
40+
crossorigin="anonymous"></script>
41+
</body>
42+
43+
</html>

tests/test_currency.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CURRENCY = '/currency'
2+
CUSTOM_DATE = "/2021-1-3"
3+
4+
5+
def test_router_good(client):
6+
resp = client.get(CURRENCY)
7+
assert resp.ok
8+
resp = client.get(CURRENCY + CUSTOM_DATE)
9+
assert resp.ok
10+
assert b'Currency</button>' in resp.content

0 commit comments

Comments
 (0)