diff --git a/types/types.go b/types/types.go index 6691b7b..bdfe927 100644 --- a/types/types.go +++ b/types/types.go @@ -28,9 +28,10 @@ type HumanLegibleTransaction struct { type ChartjsData struct { Labels []string `json:"labels"` - DataSets []DataSet `json:"datasets"` -} - -type DataSet struct { Data []int `json:"data"` } + +type TwoIntsItem struct { + Item1 int + Item2 int +} diff --git a/web/dashboard.templ b/web/dashboard.templ index ec15ce8..1bb2944 100644 --- a/web/dashboard.templ +++ b/web/dashboard.templ @@ -8,18 +8,23 @@ templ dashboard() {
Income/Expenses - +
-
-
+
+
-
+
+
+
diff --git a/web/data_endpoints.go b/web/data_endpoints.go index 147ed77..76fedb8 100644 --- a/web/data_endpoints.go +++ b/web/data_endpoints.go @@ -8,6 +8,7 @@ import ( "net/http" "time" + "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" "nickiel.net/recount_server/types" ) @@ -56,3 +57,28 @@ func getExpenditureChart(w http.ResponseWriter, req *http.Request) { w.Write(json_data); } + +func getAccountSummaries(w http.ResponseWriter, req *http.Request) { + accounts := make([]types.TwoIntsItem, 20) + for i := 0; i < 20; i++ { + accounts[i] = types.TwoIntsItem {Item1: i*100, Item2: i+5} + } + component := account_summary_rows(&accounts) + component.Render(context.Background(), w) +} + +func getAccountSummaryChart(w http.ResponseWriter, req *http.Request) { + accountID := chi.URLParam(req, "accountID") + + data_package := types.ChartjsData { + Labels: []string {accountID, "1/10", "1/17", "1/24"}, + Data: []int {100, 0, -50, 25}, + } + + json_data, err := json.Marshal(data_package); + if err != nil { + log.Fatal().Err(err).Msg("Could not jsonify data_package"); + } + + w.Write(json_data); +} diff --git a/web/dataendpoints.templ b/web/dataendpoints.templ index 0052334..4119418 100644 --- a/web/dataendpoints.templ +++ b/web/dataendpoints.templ @@ -26,3 +26,33 @@ templ transaction_rows(transactions *[]types.HumanLegibleTransaction) { } } + +templ account_summary_rows(accounts *[]types.TwoIntsItem){ + for _, value := range *accounts { +
+
+ Account: {strconv.Itoa(value.Item2)} +
+
+
+ +
+
+ if value.Item1 > 0 { + + -${strconv.Itoa(value.Item1)} + + } else { + + +${strconv.Itoa(value.Item1)} + + } +
+
+
+ } +} diff --git a/web/router.go b/web/router.go index 364fc5d..4333612 100644 --- a/web/router.go +++ b/web/router.go @@ -28,7 +28,9 @@ func WebRouter() http.Handler { r := chi.NewRouter() r.Get("/", getIndex) r.Get("/web/transaction_table_rows", getTransactions) + r.Get("/web/account_summaries", getAccountSummaries) r.Get("/web/dashboard/expenditure_chart", getExpenditureChart) + r.Get("/web/dashboard/account_summary/{accountID}", getAccountSummaryChart) r.Get("/hello", getHello) r.Handle("/chart.js/*", http.StripPrefix("/chart.js/", http.FileServer(http.Dir("web/node_modules/chart.js/")))) r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static/")))) diff --git a/web/sass/utility-classes.scss b/web/sass/utility-classes.scss index bcec7b4..89f7978 100644 --- a/web/sass/utility-classes.scss +++ b/web/sass/utility-classes.scss @@ -20,6 +20,9 @@ $directions: ( .m-#{$size} { margin: $val; } + .p-#{$size} { + padding: $val; + } @each $dir, $dir-val in $directions { .m#{$dir}-#{$size} { margin-#{$dir-val}: $val; @@ -35,7 +38,7 @@ $directions: ( } .my-#{$size} { margin-top: $val; - margin-right: $val; + margin-bottom: $val; } .px-#{$size} { padding-left: $val; @@ -46,6 +49,9 @@ $directions: ( padding-bottom: $val; } } +.m-auto { + margin: auto; +} .my-auto { margin-top: auto; margin-bottom: auto; @@ -107,6 +113,9 @@ $w_h_sizes: ( .t-e { text-align: end; } +.t-m { + text-align: center; +} table.table { color: var(--#{$prefix}-text); diff --git a/web/static/chart_functions.js b/web/static/chart_functions.js index 7fdd017..e6b9125 100644 --- a/web/static/chart_functions.js +++ b/web/static/chart_functions.js @@ -27,10 +27,117 @@ function createDiagonalPattern(color = '#ffffff') { return c.createPattern(shape, 'repeat') } -function fill_charts() { +function historical_vs_current_chart(jsonData, element) { const style = getComputedStyle(document.body); const red_color = style.getPropertyValue("--pf-red"); const green_color = style.getPropertyValue("--pf-green"); + const legend_bg = style.getPropertyValue("--pf-overlay2"); + const config = { + type: "bar", + data: { + labels: jsonData.labels, + datasets: [{ + label: "Historical", + data: [ + jsonData.income_data[0], + jsonData.expenses_data[0] + ], + backgroundColor: [ + createDiagonalPattern(green_color), + createDiagonalPattern(red_color) + ] + }, + { + label: "Last 30 Days", + data: [ + jsonData.income_data[1], + jsonData.expenses_data[1] + ], + backgroundColor: [ + green_color, + red_color + ] + }] + }, + options: { + maintainAspectRatio: false, + responsive: true, + scales: { + y: { + beginAtZero: true + } + }, + plugins: { + legend: { + display: true, + labels: { + boxWidth: 20, + position: "bottom", + generateLabels: function(chart) { + var labels = Chart.defaults.plugins.legend.labels.generateLabels(chart); + for (var key in labels) { + if (labels[key].text == "Historical") { + labels[key].fillStyle = createDiagonalPattern(legend_bg); + } else { + labels[key].fillStyle = legend_bg; + } + + labels[key].strokeStyle = "rgba(33, 44, 22, 0.7)"; + } + return labels; + } + } + } + } + } + }; + new Chart(element, config); + +} + +function sparkline_summary_chart(jsonData, element) { + const style = getComputedStyle(document.body); + const red_color = style.getPropertyValue("--pf-red"); + const green_color = style.getPropertyValue("--pf-green"); + const legend_bg = style.getPropertyValue("--pf-overlay2"); + const config = { + type: "line", + data: { + labels: jsonData.labels, + datasets: [{ + label: "Historical", + data: jsonData.data + }] + }, + options: { + maintainAspectRatio: false, + responsive: true, + scales: { + y: { + ticks: { + display: true, + callback: function(value, index, values) { + if (value === 0) { + return value; + } else { + return null; + } + }, + }, + suggestedMin: 5 + } + }, + plugins: { + legend: { + display: false + } + } + }, + }; + new Chart(element, config); +} + +function fill_charts() { document.querySelectorAll(".chartjs-chart").forEach(function (el) { var url = el.dataset.chartEndpoint; var type = el.dataset.chartType; @@ -43,66 +150,11 @@ function fill_charts() { } return response.json(); }).then(jsonData => { - const config = { - type: type, - data: { - labels: jsonData.labels, - datasets: [{ - label: "Historical", - data: [ - jsonData.income_data[0], - jsonData.expenses_data[0] - ], - backgroundColor: [ - createDiagonalPattern(green_color), - createDiagonalPattern(red_color) - ] - }, - { - label: "Last 30 Days", - data: [ - jsonData.income_data[1], - jsonData.expenses_data[1] - ], - backgroundColor: [ - green_color, - red_color - ] - }] - }, - options: { - maintainAspectRatio: false, - responsive: true, - scales: { - y: { - beginAtZero: true - } - }, - plugins: { - legend: { - display: true, - labels: { - boxWidth: 20, - position: "bottom", - generateLabels: function(chart) { - var labels = Chart.defaults.plugins.legend.labels.generateLabels(chart); - for (var key in labels) { - if (labels[key].text == "Historical") { - labels[key].fillStyle = createDiagonalPattern("#888888"); - } else { - labels[key].fillStyle = "#88888840" - } - - labels[key].strokeStyle = "rgba(33, 44, 22, 0.7)"; - } - return labels; - } - } - } - } + if (type == "historical_vs_current") { + historical_vs_current_chart(jsonData, el); + } else if (type == "sparkline_summary") { + sparkline_summary_chart(jsonData, el); } - }; - new Chart(el, config); }).catch(error => { console.error("Unable to set up chart: ", error) }); diff --git a/web/static/index.js b/web/static/index.js index c973658..2178eb1 100644 --- a/web/static/index.js +++ b/web/static/index.js @@ -50,4 +50,6 @@ function load_in_table() { const trigger_table_animation = debounce(load_in_table, 100); -export {register_handlers, trigger_table_animation, fill_charts}; +const fill_all_charts = debounce(fill_charts, 500); + +export {register_handlers, trigger_table_animation, fill_all_charts}; diff --git a/web/templates/index.html b/web/templates/index.html index 7bfa3a6..b1ed539 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -61,14 +61,14 @@