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

modified frontend so it looks great and works

parent 3dd20147
......@@ -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: | H:

frontend/src/assets/bau-1.png

2.15 MB | W: | H:

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
<template>
<div class="chart-card">
<h3>{{ title }}</h3>
<Line :data="chartData" :options="chartOptions" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
LineElement,
PointElement,
CategoryScale,
LinearScale
} from 'chart.js';
import { Line } from 'vue-chartjs';
import type { ChartData, ChartOptions } from 'chart.js';
// ⛳️ WICHTIG: Registrierung außerhalb von defineComponent
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
PointElement,
CategoryScale,
LinearScale
);
export default defineComponent({
name: 'ChartCard',
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
<div class="chart-card">
<h3>{{ title }}</h3>
<Line :data="chartData" :options="chartOptions" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
LineElement,
PointElement,
CategoryScale,
LinearScale
} from 'chart.js'
import { Line } from 'vue-chartjs'
import type { ChartData, ChartOptions } from 'chart.js'
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
PointElement,
CategoryScale,
LinearScale
)
export default defineComponent({
name: 'ChartCard',
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 }
},
computed: {
chartData(): ChartData<'line'> {
return {
labels: this.labels,
datasets: [
{
label: this.title,
data: this.data,
borderColor: this.borderColor,
backgroundColor: this.borderColor + '33',
fill: true,
tension: 0.3
}
]
}
},
computed: {
chartData(): ChartData<'line'> {
return {
labels: this.labels,
datasets: [
{
label: this.title,
data: this.data,
fill: false,
borderColor: this.borderColor,
tension: 0.3
}
]
};
},
chartOptions(): ChartOptions<'line'> {
return {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
};
chartOptions(): ChartOptions<'line'> {
return {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'top' },
title: { display: false }
},
scales: {
y: { beginAtZero: true }
}
}
}
});
</script>
<style scoped>
.chart-card {
width: 800px;
height: 750px;
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>
\ No newline at end of file
})
</script>
<style scoped>
.chart-card {
width: 1000px;
height: 500px;
background: white;
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>
<ChartCard
title="CO₂ Verlauf"
:labels="labels"
:data="co2Data"
borderColor="#ff6384"
/>
<!-- Debug-Ausgabe -->
<pre>Labels: {{ labels }}</pre>
<pre>CO₂: {{ co2Data }}</pre>
<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"
/>
<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 ''
}
}
async function loadData() {
if (!start.value || !stop.value) return
const startISO = toISOStringSafe(start.value)
const stopISO = toISOStringSafe(stop.value)
if (!response.ok) {
throw new Error(`HTTP-Fehler: ${response.status}`)
}
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