Commit 69440d7b authored by Gezer's avatar Gezer
Browse files

added Cards for frontend and two new endpoints

parent ae3c6c7f
No related merge requests found
Showing with 287 additions and 0 deletions
+287 -0
...@@ -11,4 +11,6 @@ urlpatterns = [ ...@@ -11,4 +11,6 @@ urlpatterns = [
path("api/get_rooms", views.get_rooms, name="get_rooms"), path("api/get_rooms", views.get_rooms, name="get_rooms"),
path("api/room_data_csv", views.room_data_csv_view, name="room_data_csv_view"), path("api/room_data_csv", views.room_data_csv_view, name="room_data_csv_view"),
path("api/room_data_csv_download", views.room_data_csv_download, name="room_data_csv_download"), path("api/room_data_csv_download", views.room_data_csv_download, name="room_data_csv_download"),
path("api/get_rooms_from_building", views.get_rooms_from_building, name="get_rooms_from_building"),
path("api/get_bau", views.get_bau, name="get_bau"),
] ]
...@@ -130,6 +130,51 @@ def get_rooms(request): ...@@ -130,6 +130,51 @@ def get_rooms(request):
return JsonResponse({"rooms": sorted(rooms)}) return JsonResponse({"rooms": sorted(rooms)})
@require_http_methods(["GET"])
def get_rooms_from_building(request):
building = request.GET.get("building")
if not building:
return JsonResponse({"error": "Missing 'building' parameter"}, status=400)
client = InfluxDBHelper(
url=os.getenv("INFLUXDB_URL"),
token=os.getenv("INFLUXDB_TOKEN"),
org=os.getenv("INFLUXDB_ORG"),
bucket=os.getenv("INFLUXDB_BUCKET"),
)
tables = client.list_rooms()
rooms = set()
for table in tables:
for record in table.records:
room = record.get_value()
if isinstance(room, str) and room.startswith(f"{building}/"):
rooms.add(room)
return JsonResponse({"building": building, "rooms": sorted(rooms)})
@require_http_methods(["GET"])
def get_bau(request):
client = InfluxDBHelper(
url=os.getenv("INFLUXDB_URL"),
token=os.getenv("INFLUXDB_TOKEN"),
org=os.getenv("INFLUXDB_ORG"),
bucket=os.getenv("INFLUXDB_BUCKET"),
)
tables = client.list_rooms()
baus = set()
for table in tables:
for record in table.records:
room = record.get_value()
if isinstance(room, str) and "/" in room:
bau = room.split("/")[0]
baus.add(bau)
return JsonResponse({"baus": sorted(baus)})
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def room_data_csv_view(request): def room_data_csv_view(request):
......
frontend/src/assets/bau-1.png

1.25 MB

<template>
<RouterLink :to="`/buildings/${buildingId}`" class="bau-card">
<div class="card-background" :style="{ backgroundImage: `url(${image})` }"></div>
<div class="card-content">
<h3>{{ title }}</h3>
<p>{{ description }}</p>
</div>
</RouterLink>
</template>
<script setup lang="ts">
defineProps<{
title: string
description: string
image: string
buildingId: string
}>()
</script>
<style scoped>
.bau-card {
display: block;
width: 100%;
max-width: 400px;
border-radius: 8px;
overflow: hidden;
text-decoration: none;
color: inherit;
background-color: white;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
transition: transform 0.2s ease;
}
.bau-card:hover {
transform: translateY(-4px);
}
.card-background {
height: 130px;
background-size: cover;
background-position: center;
background-color: #e0e0e0;
}
.card-content {
padding: 1rem;
}
.card-content h3 {
margin: 0;
color: darkred;
}
.card-content p {
margin: 0.3rem 0 0;
color: #555;
font-size: 0.9rem;
}
</style>
...@@ -10,6 +10,7 @@ import { RouterLink, RouterView } from 'vue-router' ...@@ -10,6 +10,7 @@ import { RouterLink, RouterView } from 'vue-router'
<RouterLink to="/">Home</RouterLink> <RouterLink to="/">Home</RouterLink>
<RouterLink to="/login">Login</RouterLink> <RouterLink to="/login">Login</RouterLink>
<RouterLink to="/about">About</RouterLink> <RouterLink to="/about">About</RouterLink>
<RouterLink to="/buildingsView">Gebäude</RouterLink>
<RouterLink to="/register">Register</RouterLink> <RouterLink to="/register">Register</RouterLink>
</nav> </nav>
</div> </div>
......
<template>
<RouterLink :to="`/rooms/${room}`" class="room-card">
<div class="card-content">
<h3>{{ room }}</h3>
</div>
</RouterLink>
</template>
<script setup lang="ts">
defineProps<{
room: string
}>()
</script>
<style scoped>
.room-card {
display: block;
background: #f9f9f9;
border-radius: 8px;
text-decoration: none;
color: #333;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: transform 0.2s ease;
padding: 1rem;
text-align: center;
}
.room-card:hover {
transform: translateY(-4px);
background-color: #ffeaea;
}
.card-content h3 {
margin: 0;
color: darkred;
}
</style>
...@@ -2,6 +2,8 @@ import { createRouter, createWebHistory } from 'vue-router' ...@@ -2,6 +2,8 @@ import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue' import HomeView from '../views/HomeView.vue'
import LoginView from '../views/LoginView.vue' import LoginView from '../views/LoginView.vue'
import RegisterView from '../views/RegisterView.vue' import RegisterView from '../views/RegisterView.vue'
import RoomNavView from '../views/RoomNavView.vue'
import BuildingsView from '../views/BuildingsView.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
...@@ -21,6 +23,17 @@ const router = createRouter({ ...@@ -21,6 +23,17 @@ const router = createRouter({
name: 'register', name: 'register',
component: RegisterView, component: RegisterView,
}, },
{
path: '/roomNav',
name: 'roomNav',
component: RoomNavView,
},
{
path: '/buildingsView',
name: 'buildingsView',
component: BuildingsView,
},
{ {
path: '/about', path: '/about',
name: 'about', name: 'about',
......
<script setup lang="ts">
import BauCard from '../components/BauCard.vue'
const buildings = [
{
id: '1',
title: 'Bau 1',
description: 'Zentralgebäude mit Laboren',
image: '../assets/bau-1.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
{
id: '2',
title: 'Bau 2',
description: 'Informatik und IT-Räume',
image: '/images/building2.png',
},
]
</script>
<template>
<div class="building-grid">
<BauCard
v-for="bau in buildings"
:key="bau.id"
:building-id="bau.id"
:title="bau.title"
:description="bau.description"
:image="bau.image"
/>
</div>
</template>
<style scoped>
.building-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
padding: 2rem;
}
</style>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getCSRFToken } from '../stores/auth'
import RoomCard from '../components/RoomCard.vue'
const rooms = ref<string[]>([])
const error = ref<string | null>(null)
const fetchRooms = async () => {
try {
const response = await fetch('http://localhost:8000/api/get_rooms', {
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(),
},
credentials: 'include',
})
const data = await response.json()
if (response.ok && data.rooms) {
rooms.value = data.rooms
} else {
error.value = 'Fehler beim Laden der Räume.'
}
} catch (err) {
error.value = 'Serverfehler: ' + err
}
}
onMounted(fetchRooms)
</script>
<template>
<div class="room-container">
<h2>Räume</h2>
<p v-if="error" class="error">{{ error }}</p>
<div class="card-grid">
<RoomCard v-for="room in rooms" :key="room" :room="room" />
</div>
</div>
</template>
<style scoped>
.room-container {
padding: 2rem;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
margin-top: 1rem;
}
.error {
color: red;
}
</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