108 lines
3.0 KiB
JavaScript
108 lines
3.0 KiB
JavaScript
window.loadCosts = async function(){
|
|
|
|
const resources = window.resources || []
|
|
const domains = await api(API + "/domains")
|
|
|
|
let month = 0
|
|
let year = 0
|
|
let domainYear = 0
|
|
|
|
const parts = []
|
|
let resourceYearTotal = 0
|
|
|
|
resources.forEach(r => {
|
|
|
|
if(r.kosten_monat){
|
|
month += parseFloat(r.kosten_monat)
|
|
}
|
|
|
|
const resourceYear = getResourceYearCost(r)
|
|
resourceYearTotal += resourceYear
|
|
|
|
if(resourceYear > 0){
|
|
parts.push({
|
|
label: r.name || "Unbenannter Server",
|
|
amount: resourceYear,
|
|
type: "server",
|
|
colorIndex: parts.length
|
|
})
|
|
}
|
|
|
|
})
|
|
|
|
domains.forEach(d => {
|
|
|
|
if(d.yearly_cost){
|
|
domainYear += parseFloat(d.yearly_cost)
|
|
}
|
|
|
|
})
|
|
|
|
document.getElementById("costMonth").innerText = month.toFixed(2)
|
|
document.getElementById("costYear").innerText = resourceYearTotal.toFixed(2)
|
|
document.getElementById("costDomain").innerText = domainYear.toFixed(2)
|
|
|
|
const total = resourceYearTotal + domainYear
|
|
|
|
document.getElementById("costTotal").innerText = total.toFixed(2)
|
|
renderCostChart(parts, domainYear, total)
|
|
|
|
}
|
|
|
|
function getResourceYearCost(resource){
|
|
if(resource.kosten_jahr){
|
|
return parseFloat(resource.kosten_jahr) || 0
|
|
}
|
|
|
|
if(resource.kosten_monat){
|
|
return (parseFloat(resource.kosten_monat) || 0) * 12
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
function renderCostChart(serverParts, domainYear, total){
|
|
const container = document.getElementById("costChart")
|
|
if(!container) return
|
|
|
|
const parts = [...serverParts]
|
|
|
|
if(domainYear > 0){
|
|
parts.push({
|
|
label: "Domains gesamt",
|
|
amount: domainYear,
|
|
type: "domains",
|
|
colorIndex: parts.length
|
|
})
|
|
}
|
|
|
|
if(!total || !parts.length){
|
|
container.innerHTML = `<div class="cost-empty">Keine Kosten erfasst</div>`
|
|
return
|
|
}
|
|
|
|
const sortedParts = [...parts].sort((a, b) => b.amount - a.amount)
|
|
|
|
container.innerHTML = `
|
|
<div class="cost-bar">
|
|
${sortedParts.map(part => `
|
|
<div class="cost-segment ${part.type}"
|
|
style="width:${((part.amount / total) * 100).toFixed(2)}%; --segment-index:${part.colorIndex}"
|
|
title="${part.label}: ${part.amount.toFixed(2)} EUR">
|
|
</div>
|
|
`).join("")}
|
|
</div>
|
|
<div class="cost-breakdown">
|
|
${sortedParts
|
|
.map(part => `
|
|
<div class="cost-row">
|
|
<span class="cost-dot ${part.type}" style="--segment-index:${part.colorIndex}"></span>
|
|
<span class="cost-label">${part.label}</span>
|
|
<span class="cost-value">${part.amount.toFixed(2)} EUR</span>
|
|
<span class="cost-share">${((part.amount / total) * 100).toFixed(1)}%</span>
|
|
</div>
|
|
`).join("")}
|
|
</div>
|
|
`
|
|
}
|