Enhance MoneyHistoryGraphDialog: Add axis labels for better data visualization, improve graph scaling logic, and implement money and date formatting methods. Update localization files to include "yesterday" translations in German and English, enhancing user experience and clarity in financial data representation.
This commit is contained in:
@@ -32,13 +32,46 @@
|
||||
{{ $t('falukant.moneyHistory.graph.noData') }}
|
||||
</div>
|
||||
<div v-else class="graph-container">
|
||||
<svg viewBox="0 0 100 40" preserveAspectRatio="none" class="graph-svg">
|
||||
<svg viewBox="0 0 100 50" preserveAspectRatio="none" class="graph-svg">
|
||||
<!-- Y-Achse Beschriftungen (Geldbeträge) -->
|
||||
<g class="y-axis-labels">
|
||||
<text
|
||||
v-for="(label, index) in yAxisLabels"
|
||||
:key="'y-' + index"
|
||||
:x="2"
|
||||
:y="label.y"
|
||||
class="axis-label y-label"
|
||||
text-anchor="start"
|
||||
>
|
||||
{{ label.text }}
|
||||
</text>
|
||||
</g>
|
||||
|
||||
<!-- X-Achse Beschriftungen (Zeit) -->
|
||||
<g class="x-axis-labels">
|
||||
<text
|
||||
v-for="(label, index) in xAxisLabels"
|
||||
:key="'x-' + index"
|
||||
:x="label.x"
|
||||
:y="47"
|
||||
class="axis-label x-label"
|
||||
text-anchor="middle"
|
||||
>
|
||||
{{ label.text }}
|
||||
</text>
|
||||
</g>
|
||||
|
||||
<!-- Graph-Linie -->
|
||||
<polyline
|
||||
:points="graphPolylinePoints"
|
||||
fill="none"
|
||||
stroke="#F9A22C"
|
||||
stroke-width="0.7"
|
||||
stroke-width="0.3"
|
||||
/>
|
||||
|
||||
<!-- Achsenlinien -->
|
||||
<line x1="8" y1="2" x2="8" y2="42" stroke="#666" stroke-width="0.2" />
|
||||
<line x1="8" y1="42" x2="98" y2="42" stroke="#666" stroke-width="0.2" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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'
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
"close": "Close",
|
||||
"loading": "Loading history...",
|
||||
"noData": "No entries for the selected period.",
|
||||
"yesterday": "Yesterday",
|
||||
"range": {
|
||||
"label": "Range",
|
||||
"today": "Today",
|
||||
|
||||
Reference in New Issue
Block a user