diff --git a/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue b/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue
index c3ce6ba..da805fc 100644
--- a/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue
+++ b/frontend/src/dialogues/falukant/MoneyHistoryGraphDialog.vue
@@ -32,13 +32,46 @@
{{ $t('falukant.moneyHistory.graph.noData') }}
-
@@ -59,6 +92,10 @@ export default {
graphRange: '24h',
graphData: [],
graphLoading: false,
+ _minX: null,
+ _maxX: null,
+ _minY: null,
+ _maxY: null,
}
},
computed: {
@@ -70,19 +107,52 @@ export default {
if (d.moneyBefore != null) return Number(d.moneyBefore)
return 0
})
- const minX = Math.min(...xs)
- const maxX = Math.max(...xs)
- const minY = Math.min(...ys)
- const maxY = Math.max(...ys)
- const spanX = maxX - minX || 1
- const spanY = maxY - minY || 1
+ this._minX = Math.min(...xs)
+ this._maxX = Math.max(...xs)
+ this._minY = Math.min(...ys)
+ this._maxY = Math.max(...ys)
+ const spanX = this._maxX - this._minX || 1
+ const spanY = this._maxY - this._minY || 1
return xs.map((x, i) => {
- const normX = ((x - minX) / spanX) * 100
- const normY = 40 - ((ys[i] - minY) / spanY) * 35 - 2 // etwas Rand oben/unten
+ const normX = 8 + ((x - this._minX) / spanX) * 90 // 8-98 Bereich für X
+ const normY = 42 - ((ys[i] - this._minY) / spanY) * 38 // 2-42 Bereich für Y
return `${normX.toFixed(2)},${normY.toFixed(2)}`
}).join(' ')
},
+ yAxisLabels() {
+ if (!this.graphData.length || !this._minY || !this._maxY) return []
+ const labels = []
+ const numLabels = 5
+ const span = this._maxY - this._minY || 1
+
+ for (let i = 0; i <= numLabels; i++) {
+ const value = this._minY + (span * i / numLabels)
+ const y = 42 - (i / numLabels) * 38
+ labels.push({
+ y: y + 1.5, // Zentrierung
+ text: this.formatMoney(value)
+ })
+ }
+ return labels
+ },
+ xAxisLabels() {
+ if (!this.graphData.length || !this._minX || !this._maxX) return []
+ const labels = []
+ const numLabels = 5
+ const span = this._maxX - this._minX || 1
+
+ for (let i = 0; i <= numLabels; i++) {
+ const timestamp = this._minX + (span * i / numLabels)
+ const x = 8 + (i / numLabels) * 90
+ const date = new Date(timestamp)
+ labels.push({
+ x: x,
+ text: this.formatDate(date)
+ })
+ }
+ return labels
+ },
},
methods: {
open() {
@@ -96,6 +166,11 @@ export default {
range: this.graphRange,
})
this.graphData = Array.isArray(response.data) ? response.data : []
+ // Reset min/max für computed properties
+ this._minX = null
+ this._maxX = null
+ this._minY = null
+ this._maxY = null
} catch (error) {
console.error('Error loading money history graph data:', error)
this.graphData = []
@@ -103,6 +178,35 @@ export default {
this.graphLoading = false
}
},
+ formatMoney(amount) {
+ return new Intl.NumberFormat(navigator.language, {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0,
+ style: 'currency',
+ currency: 'EUR'
+ }).format(amount)
+ },
+ formatDate(date) {
+ const now = new Date()
+ const diffMs = now - date
+ const diffHours = diffMs / (1000 * 60 * 60)
+
+ if (diffHours < 24) {
+ // Heute: nur Uhrzeit
+ return date.toLocaleTimeString(navigator.language, { hour: '2-digit', minute: '2-digit' })
+ } else if (diffHours < 48) {
+ // Gestern: "Gestern" + Uhrzeit
+ return this.$t('falukant.moneyHistory.graph.yesterday') + ' ' + date.toLocaleTimeString(navigator.language, { hour: '2-digit', minute: '2-digit' })
+ } else {
+ // Älter: Datum + Uhrzeit
+ return date.toLocaleString(navigator.language, {
+ day: '2-digit',
+ month: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit'
+ })
+ }
+ },
},
}
@@ -141,6 +245,19 @@ export default {
border-radius: 4px;
}
+.axis-label {
+ font-size: 2.5px;
+ fill: #333;
+}
+
+.y-label {
+ dominant-baseline: middle;
+}
+
+.x-label {
+ dominant-baseline: hanging;
+}
+
.graph-loading,
.graph-no-data {
margin: 1rem 0;
diff --git a/frontend/src/i18n/locales/de/falukant.json b/frontend/src/i18n/locales/de/falukant.json
index 00bceb1..7262285 100644
--- a/frontend/src/i18n/locales/de/falukant.json
+++ b/frontend/src/i18n/locales/de/falukant.json
@@ -587,6 +587,7 @@
"close": "Schließen",
"loading": "Lade Verlauf...",
"noData": "Für den gewählten Zeitraum liegen keine Buchungen vor.",
+ "yesterday": "Gestern",
"range": {
"label": "Zeitraum",
"today": "Heute",
diff --git a/frontend/src/i18n/locales/en/falukant.json b/frontend/src/i18n/locales/en/falukant.json
index afe0335..1b3c98d 100644
--- a/frontend/src/i18n/locales/en/falukant.json
+++ b/frontend/src/i18n/locales/en/falukant.json
@@ -117,6 +117,7 @@
"close": "Close",
"loading": "Loading history...",
"noData": "No entries for the selected period.",
+ "yesterday": "Yesterday",
"range": {
"label": "Range",
"today": "Today",