Initial commit — energy dashboard frontend (TimescaleDB + Vue/Chart.js)

This commit is contained in:
2026-04-18 11:14:12 +02:00
commit 9fa7d36610
28 changed files with 3243 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
const BASE = '/energy/api'
async function request<T>(path: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${BASE}${path}`, {
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
...options,
})
if (res.status === 401) {
if (window.location.pathname !== '/energy/login') {
window.location.href = '/energy/login'
}
throw new Error('Unauthorized')
}
if (!res.ok) {
const body = await res.json().catch(() => ({ error: res.statusText }))
throw new Error(body.error || res.statusText)
}
return res.json()
}
export interface EnergyBar {
time: string
buy: number
sell: number
produce: number
consume: number
}
export interface PowerPoint {
time: string
pv: number
house: number
barn: number
}
export interface BatteryPoint {
time: string
level: number
}
export const api = {
login(username: string, password: string) {
return request<{ status: string }>('/login', {
method: 'POST',
body: JSON.stringify({ username, password }),
})
},
logout() {
return request<{ status: string }>('/logout', { method: 'POST' })
},
checkAuth() {
return request<{ status: string }>('/auth/check')
},
getBars(period: 'day' | 'week' | 'month', count: number) {
return request<{ bars: EnergyBar[] }>(`/bars?period=${period}&count=${count}`)
},
getPower(range: string) {
return request<{ points: PowerPoint[] }>(`/power?range=${range}`)
},
getBattery(range: string) {
return request<{ points: BatteryPoint[] }>(`/battery?range=${range}`)
},
}