Commit 6068d9e3 authored by Gezer's avatar Gezer
Browse files

modified frontend so it looks great and works

parent 3dd20147
No related merge requests found
Showing with 234 additions and 138 deletions
+234 -138
......@@ -3,12 +3,14 @@ import NavBar from './components/NavBar.vue';
</script>
<template>
<NavBar></NavBar>
<main class="content">
<NavBar />
</main>
</template>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
.content {
padding-top: 100px; /* Platz für fixierten Header (60px Logo + Padding) */
}
</style>
frontend/src/assets/bau-1.png

1.25 MB | W: 0px | H: 0px

frontend/src/assets/bau-1.png

2.15 MB | W: 0px | H: 0px

frontend/src/assets/bau-1.png
frontend/src/assets/bau-1.png
frontend/src/assets/bau-1.png
frontend/src/assets/bau-1.png
  • 2-up
  • Swipe
  • Onion skin
frontend/src/assets/bau-2.png

259 KB

frontend/src/assets/bau-3.png

253 KB

frontend/src/assets/bau-8.png

118 KB

......@@ -3,13 +3,13 @@
<h3>{{ title }}</h3>
<Line :data="chartData" :options="chartOptions" />
</div>
</template>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import {
import {
Chart as ChartJS,
Title,
Tooltip,
......@@ -18,12 +18,11 @@
PointElement,
CategoryScale,
LinearScale
} from 'chart.js';
import { Line } from 'vue-chartjs';
import type { ChartData, ChartOptions } from 'chart.js';
} from 'chart.js'
import { Line } from 'vue-chartjs'
import type { ChartData, ChartOptions } from 'chart.js'
// ⛳️ WICHTIG: Registrierung außerhalb von defineComponent
ChartJS.register(
ChartJS.register(
Title,
Tooltip,
Legend,
......@@ -31,30 +30,16 @@
PointElement,
CategoryScale,
LinearScale
);
)
export default defineComponent({
export default defineComponent({
name: 'ChartCard',
components: {
Line
},
components: { Line },
props: {
title: {
type: String,
required: true
},
labels: {
type: Array as PropType<string[]>,
required: true
},
data: {
type: Array as PropType<number[]>,
required: true
},
borderColor: {
type: String,
required: true
}
title: { type: String, required: true },
labels: { type: Array as PropType<string[]>, required: true },
data: { type: Array as PropType<number[]>, required: true },
borderColor: { type: String, required: true }
},
computed: {
chartData(): ChartData<'line'> {
......@@ -64,41 +49,45 @@
{
label: this.title,
data: this.data,
fill: false,
borderColor: this.borderColor,
backgroundColor: this.borderColor + '33',
fill: true,
tension: 0.3
}
]
};
}
},
chartOptions(): ChartOptions<'line'> {
return {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'top' },
title: { display: false }
},
scales: {
y: {
beginAtZero: true
y: { beginAtZero: true }
}
}
};
}
}
});
</script>
})
</script>
<style scoped>
.chart-card {
width: 800px;
height: 750px;
<style scoped>
.chart-card {
width: 1000px;
height: 500px;
background: white;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.chart-card h3 {
text-align: center;
margin-bottom: 0.5rem;
font-size: 1rem;
}
</style>
padding: 1.5rem;
border-radius: 10px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.chart-card h3 {
text-align: center;
margin-bottom: 1rem;
font-size: 1.25rem;
font-weight: 600;
}
</style>
......@@ -9,10 +9,8 @@ import { RouterLink, RouterView } from 'vue-router'
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/login">Login</RouterLink>
<RouterLink to="/about">About</RouterLink>
<RouterLink to="/buildingsView">Gebäude</RouterLink>
<RouterLink to="/charts">Charts</RouterLink>
<RouterLink to="/register">Registrieren</RouterLink>
<RouterLink to="/buildingsView">Gebäude</RouterLink>
</nav>
</div>
</header>
......
......@@ -8,25 +8,25 @@ const buildings = [
id: '1',
title: 'Bau 1',
description: 'Zentralgebäude mit Laboren',
image: '../assets/bau-1.png',
image: new URL('@/assets/bau-1.png', import.meta.url).href,
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
image: new URL('@/assets/bau-2.png', import.meta.url).href,
},
{
id: '3',
title: 'Bau 3',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
image: new URL('@/assets/bau-3.png', import.meta.url).href,
},
{
id: '8',
title: 'Bau 8',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
image: new URL('@/assets/bau-8.png', import.meta.url).href,
}
]
......@@ -90,19 +90,20 @@ async function loadRooms(buildingId: string) {
display: flex;
padding: 2rem;
gap: 2rem;
align-items: flex-start; /* wichtige Ergänzung */
}
.building-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
display: flex;
flex-direction: column; /* Gebäude untereinander */
gap: 1.5rem;
flex: 2;
flex-shrink: 0;
}
.room-panel {
flex: 1;
display: flex;
flex-direction: column;
gap: 1rem;
flex-grow: 1;
}
</style>
......@@ -2,16 +2,38 @@
<div class="chart-view">
<h2>Daten für Raum: {{ room }}</h2>
<div class="time-form">
<label>
Start:
<input class="datetime" type="datetime-local" v-model="start" />
</label>
<label>
Stop:
<input class="datetime" type="datetime-local" v-model="stop" />
</label>
<button @click="loadData">Zeitraum aktualisieren</button>
</div>
<div class="chart-grid">
<ChartCard
title="CO₂ Verlauf"
:labels="labels"
:data="co2Data"
borderColor="#ff6384"
/>
<!-- Debug-Ausgabe -->
<pre>Labels: {{ labels }}</pre>
<pre>CO₂: {{ co2Data }}</pre>
<ChartCard
title="Temperatur Verlauf"
:labels="labels"
:data="temperatureData"
borderColor="#36a2eb"
/>
<ChartCard
title="Luftfeuchtigkeit Verlauf"
:labels="labels"
:data="humidityData"
borderColor="#4bc0c0"
/>
</div>
</div>
</template>
......@@ -29,36 +51,83 @@ export default defineComponent({
const labels = ref<string[]>([])
const co2Data = ref<number[]>([])
const temperatureData = ref<number[]>([])
const humidityData = ref<number[]>([])
onMounted(async () => {
const start = ref('')
const stop = ref('')
function toISOStringSafe(value: string): string {
try {
const url = `http://localhost:8000/api/room_data_range?room=${encodeURIComponent(room)}&start=-7d&stop=now()`
const response = await fetch(url)
return new Date(value).toISOString()
} catch {
return ''
}
}
if (!response.ok) {
throw new Error(`HTTP-Fehler: ${response.status}`)
async function loadData() {
if (!start.value || !stop.value) return
const startISO = toISOStringSafe(start.value)
const stopISO = toISOStringSafe(stop.value)
if (new Date(startISO) >= new Date(stopISO)) {
alert('❌ Der Startzeitpunkt muss vor dem Endzeitpunkt liegen.')
return
}
const url = `http://localhost:8000/api/room_data_range?room=${encodeURIComponent(
room
)}&start=${startISO}&stop=${stopISO}`
try {
const response = await fetch(url)
if (!response.ok) throw new Error('Fehler beim Laden')
const json = await response.json()
const entries = Object.entries(json.data).sort(
([a], [b]) => new Date(a).getTime() - new Date(b).getTime()
)
const labelsArray = entries.map(([timestamp]) =>
new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
labels.value = entries.map(([timestamp]) =>
new Date(timestamp).toLocaleString([], {
day: '2-digit',
month: '2-digit',
hour: '2-digit',
minute: '2-digit',
})
)
co2Data.value = entries.map(([, values]: any) => Number(values.co2))
temperatureData.value = entries.map(([, values]: any) =>
Number(values.temperature)
)
humidityData.value = entries.map(([, values]: any) =>
Number(values.humidity)
)
const co2DataArray = entries.map(([, values]) => values.co2)
labels.value = labelsArray
co2Data.value = co2DataArray
} catch (err) {
console.error('❌ Fehler beim Laden der Daten:', err)
}
}
onMounted(async () => {
const now = new Date()
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
start.value = weekAgo.toISOString().slice(0, 16)
stop.value = now.toISOString().slice(0, 16)
await loadData()
})
return { room, labels, co2Data }
return {
room,
start,
stop,
labels,
co2Data,
temperatureData,
humidityData,
loadData,
}
},
})
</script>
......@@ -66,4 +135,41 @@ export default defineComponent({
.chart-view {
padding: 2rem;
}
.time-form {
display: flex;
gap: 1rem;
margin-bottom: 2rem;
align-items: center;
flex-wrap: wrap;
}
.time-form input {
padding: 0.5rem;
font-size: 1rem;
border-radius: 5px;
}
.time-form button {
background: #007bff;
color: white;
padding: 0.6rem 1.2rem;
border: none;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
transition: background-color 0.2s ease;
}
.time-form button:hover {
background-color: #0056b3;
}
.chart-grid {
display: flex;
flex-wrap: nowrap;
gap: 2rem;
justify-content: flex-start;
flex-direction: row;
}
</style>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment