added node modules for chartjs :(

This commit is contained in:
Nickiel12 2024-01-17 19:58:31 -08:00
parent c20830a334
commit 656e665ad7
12 changed files with 154 additions and 30 deletions

1
.gitignore vendored
View file

@ -6,6 +6,7 @@ web/*_templ.go
web/static/*.css web/static/*.css
web/static/*.css.map web/static/*.css.map
.sass-cache/* .sass-cache/*
*/node_modules/*
# --> nix # --> nix
.direnv/ .direnv/

View file

@ -75,6 +75,7 @@
default = pkgs.mkShell { default = pkgs.mkShell {
buildInputs = with pkgs; [ buildInputs = with pkgs; [
air # live go app reloading air # live go app reloading
corepack # npm install for the web folder
dart-sass dart-sass
go go
gopls gopls

View file

@ -25,3 +25,8 @@ type HumanLegibleTransaction struct {
BucketName sql.NullString `db:"bucket_name" json:"BucketName"` BucketName sql.NullString `db:"bucket_name" json:"BucketName"`
Date time.Time `db:"trns_date" json:"TransactionDate"` Date time.Time `db:"trns_date" json:"TransactionDate"`
} }
type ChartjsData struct {
Labels []string `json:"labels"`
Data []int `json:"data"`
}

View file

@ -9,6 +9,18 @@ templ dashboard() {
<i class="my-auto c-text py-3 ps-3 ms-1" data-feather="arrow-left"></i> <i class="my-auto c-text py-3 ps-3 ms-1" data-feather="arrow-left"></i>
<i class="my-auto c-text py-3 pe-3 me-1 ms-auto" data-feather="arrow-right"></i> <i class="my-auto c-text py-3 pe-3 me-1 ms-auto" data-feather="arrow-right"></i>
</div> </div>
<div class="d-flex">
<div class="my-auto mx-2 w-75">
<canvas
class="chartjs-chart"
data-chart-endpoint="/web/dashboard/expenditure_chart"
data-chart-type="bar"
id="IncomeVsExpenditureChart"
></canvas>
</div>
<div class="c-mantle">
</div>
</div>
</div> </div>
<div class="c-crust col card mx-auto cr-all"> <div class="c-crust col card mx-auto cr-all">

53
web/data_endpoints.go Normal file
View file

@ -0,0 +1,53 @@
package web
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/rs/zerolog/log"
"nickiel.net/recount_server/types"
)
const DEFAULT_RESULT_COUNT = 20;
func getTransactions(w http.ResponseWriter, req *http.Request) {
transactions := make([]types.HumanLegibleTransaction, 10)
// Populate the slice with dummy data (you can replace this with your actual data)
for i := 10; i > 0; i-- {
transaction := types.HumanLegibleTransaction{
Id: i,
Amount: fmt.Sprintf("%d.00", (i+1)*100),
Description: sql.NullString{String: fmt.Sprintf("Transaction %d", i+1), Valid: true},
AccountName: sql.NullString{String: "Savings", Valid: true},
Account: 123,
Bucket: sql.NullInt64{Int64: int64(i + 100), Valid: true},
BucketName: sql.NullString{String: fmt.Sprintf("Bucket %d", i+1), Valid: true},
Date: time.Now(),
}
transactions[10 - i] = transaction
}
component := transaction_rows(&transactions);
component.Render(context.Background(), w);
}
func getExpenditureChart(w http.ResponseWriter, req *http.Request) {
data_package := types.ChartjsData {
Labels: []string{"Income", "Expenses"},
Data: []int{500, 200},
};
json_data, err := json.Marshal(data_package);
if err != nil {
log.Fatal().Err(err).Msg("Could not jsonify data_package");
}
w.Write(json_data);
}

28
web/package-lock.json generated Normal file
View file

@ -0,0 +1,28 @@
{
"name": "web",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"chart.js": "^4.4.1"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
},
"node_modules/chart.js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
"integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=7"
}
}
}
}

5
web/package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"chart.js": "^4.4.1"
}
}

View file

@ -1,20 +1,16 @@
package web package web
import ( import (
"database/sql"
"html/template" "html/template"
"net/http" "net/http"
"bytes" "bytes"
"context" "context"
"fmt"
"time"
"github.com/a-h/templ" "github.com/a-h/templ"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"nickiel.net/recount_server/types"
) )
type TemplateState struct { type TemplateState struct {
@ -32,6 +28,7 @@ func WebRouter() http.Handler {
r := chi.NewRouter() r := chi.NewRouter()
r.Get("/", getIndex) r.Get("/", getIndex)
r.Get("/web/transaction_table_rows", getTransactions) r.Get("/web/transaction_table_rows", getTransactions)
r.Get("/web/dashboard/expenditure_chart", getExpenditureChart)
r.Get("/hello", getHello) r.Get("/hello", getHello)
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static/")))) r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static/"))))
return r return r
@ -99,27 +96,3 @@ func getHello(w http.ResponseWriter, req *http.Request) {
} }
} }
const DEFAULT_RESULT_COUNT = 20;
func getTransactions(w http.ResponseWriter, req *http.Request) {
transactions := make([]types.HumanLegibleTransaction, 10)
// Populate the slice with dummy data (you can replace this with your actual data)
for i := 10; i > 0; i-- {
transaction := types.HumanLegibleTransaction{
Id: i,
Amount: fmt.Sprintf("%d.00", (i+1)*100),
Description: sql.NullString{String: fmt.Sprintf("Transaction %d", i+1), Valid: true},
AccountName: sql.NullString{String: "Savings", Valid: true},
Account: 123,
Bucket: sql.NullInt64{Int64: int64(i + 100), Valid: true},
BucketName: sql.NullString{String: fmt.Sprintf("Bucket %d", i+1), Valid: true},
Date: time.Now(),
}
transactions[10 - i] = transaction
}
component := transaction_rows(&transactions);
component.Render(context.Background(), w);
}

View file

@ -56,6 +56,9 @@ $directions: (
.w-full { .w-full {
width: 100%; width: 100%;
} }
.w-75 {
width: 75%;
}
.w-50 { .w-50 {
width: 50%; width: 50%;
} }

View file

@ -0,0 +1,39 @@
function fill_charts() {
document.querySelectorAll(".chartjs-chart").forEach(function (el) {
var url = el.dataset.chartEndpoint;
var type = el.dataset.chartType;
fetch(url)
.then(response => {
if (!response.ok) {
console.log(response);
throw new Error("Fetch response was not ok!")
}
return response.json();
}).then(jsonData => {
const config = {
type: type,
data: {
labels: jsonData.labels,
datasets: [{
data: jsonData.data
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
};
new Chart(el, config)();
}).catch(error => {
console.error("Unable to set up chart: ", error)
});
});
}
export {fill_charts}

View file

@ -1,3 +1,5 @@
import {fill_charts} from "./chart_functions.js";
function debounce(func, delay) { function debounce(func, delay) {
let timeoutId; let timeoutId;
@ -48,4 +50,4 @@ function load_in_table() {
const trigger_table_animation = debounce(load_in_table, 100); const trigger_table_animation = debounce(load_in_table, 100);
export {register_handlers, trigger_table_animation}; export {register_handlers, trigger_table_animation, fill_charts};

View file

@ -60,13 +60,15 @@
</div> </div>
<script type="module" src="/static/index.js"></script> <script type="module" src="/static/index.js"></script>
<script type="module"> <script type="module">
import {register_handlers, trigger_table_animation} from "/static/index.js"; import {register_handlers, fill_charts, trigger_table_animation} from "/static/index.js";
register_handlers(); register_handlers();
feather.replace(); feather.replace();
htmx.onLoad(function (element) { htmx.onLoad(function (element) {
if (element.localName === "tr") { if (element.localName === "tr") {
console.log(element); console.log(element);
trigger_table_animation(); trigger_table_animation();
} else {
fill_charts();
} }
}); });
</script> </script>