redo of frontend style part 1

This commit is contained in:
“Niklas” 2024-10-10 12:01:08 +02:00
parent 4faf14c518
commit 2e2437660b
5 changed files with 312 additions and 100 deletions

View file

@ -29,5 +29,6 @@
"vite": "^5.1.5", "vite": "^5.1.5",
"vite-plugin-vuetify": "^2.0.3", "vite-plugin-vuetify": "^2.0.3",
"vue-tsc": "^2.0.6" "vue-tsc": "^2.0.6"
} },
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4"
} }

View file

@ -1,12 +1,15 @@
<template> <template>
<v-app> <v-app>
<v-main> <v-main>
<!-- <div v-if="store.token === null"> <!--
<div v-if="store.token === null">
<loginPage /> <loginPage />
</div> </div>
<div v-else> --> <div v-else>
<MainPage /> <MainPage />
<!--</div>--> </div>
-->
<MainPage />
</v-main> </v-main>
</v-app> </v-app>
</template> </template>
@ -21,6 +24,6 @@ import { store } from "./store";
html, html,
body, body,
main { main {
background-color: #e3e3e3; background-color: #2B3037;
} }
</style> </style>

View file

@ -1,13 +1,8 @@
<template> <template>
<div> <div>
<HeaderBar /> <HeaderBar />
<div class="ma-8"> <div style="margin: 15px">
<div v-if="isPending">Loading...</div> <TableCategory></TableCategory>
<ul v-else-if="data">
<li v-for="nodeGroup in data" :key="nodeGroup.groupId">
<CategoryContainer :nodeGroup="nodeGroup" />
</li>
</ul>
</div> </div>
</div> </div>
</template> </template>
@ -17,68 +12,45 @@ import HeaderBar from "./HeaderBar.vue";
import CategoryContainer from "./CategoryContainer.vue"; import CategoryContainer from "./CategoryContainer.vue";
import { useQuery } from "@tanstack/vue-query"; import { useQuery } from "@tanstack/vue-query";
import { axiosInstance } from "@/client"; import { axiosInstance } from "@/client";
import { NodeGroup } from "@/types"; import { LicenseGroup, License } from "@/types";
import { search, key } from "@/store"; import { search, key } from "@/store";
import MiniSearch from "minisearch"; import MiniSearch from "minisearch";
import { computed, provide } from "vue"; import { computed, provide } from "vue";
import TableCategory from "./TableCategory.vue";
const mockNodeGroups: NodeGroup[] = [
{
groupId: "group-1",
name: "Test Node Group 1",
nodes: [
{
uuid: "123e4567-e89b-12d3-a456-426614174000",
name: "Sensor Node A1",
status: 502,
coordla: 52.5200,
coordlong: 13.4050,
temperature: 22.5,
battery: 85,
runtime: 120,
},
{
uuid: "223e4567-e89b-12d3-a456-426614174001",
name: "Sensor Node A2",
status: 200,
coordla: 48.8566,
coordlong: 2.3522,
temperature: 20.0,
battery: 90,
runtime: 100,
},
]
},
];
const { isPending, isError, data, error } = useQuery({ const { isPending, isError, data, error } = useQuery({
queryKey: ["nodeGroups"], queryKey: ["licenses"],
queryFn: async () => { queryFn: async () => {
//hier der API-Call für die Daten const res = await axiosInstance.get<LicenseGroup[]>("/licenses");
return mockNodeGroups; console.log(res.data);
return res.data;
}, },
refetchInterval: 1 * 1, refetchInterval: 60 * 1000,
}); });
const searchEngine = computed(() => { const searchEngine = computed(() => {
const minisearch = new MiniSearch({ let minisearch = new MiniSearch({
fields: ["name", "groupId"], fields: ["name", "description", "id"],
searchOptions: { searchOptions: {
boost: { name: 2 }, boost: { name: 2 },
prefix: true, prefix: true,
}, },
}); });
let licenses: License[] = [];
if (data.value) { data.value?.forEach((group) => {
minisearch.addAll(data.value); group.licenses.forEach((license) => licenses.push(license));
} });
console.log(licenses);
minisearch.addAll(licenses);
return minisearch; return minisearch;
}); });
const searching = computed(() => search.value !== ""); const searching = computed(() => search.value !== "");
const visibleIds = computed(() => { const visibleIds = computed(() => {
return searching.value ? searchEngine.value.search(search.value).map(result => result.groupId) : []; return searchEngine.value.search(search.value).map((searchResult) => {
return searchResult.id;
});
}); });
provide(key, { provide(key, {

View file

@ -0,0 +1,141 @@
<template>
<div class="table-container">
<table class="responsive-table">
<thead>
<tr>
<th>Node/Name</th>
<th>Status</th>
<th>Latitude</th> <!-- Separate column for Latitude -->
<th>Longitude</th> <!-- Separate column for Longitude -->
<th>Battery</th>
<th>Gemessene - Temperatur</th>
<th>Laufzeit</th>
</tr>
</thead>
<tbody>
<tr v-for="(node, index) in tableData" :key="index">
<td>{{ node.name }}</td>
<td>
<span :class="node.status === 'ONLINE' ? 'status-online' : 'status-offline'">
{{ node.status }}
</span>
</td>
<td>{{ node.position.lat }}</td>
<td>{{ node.position.lng }}</td>
<td>{{ node.battery }}%</td>
<td>{{ node.temperature }}°C</td>
<td>{{ node.runtime }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "ONLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 98,
temperature: 100,
runtime: "12h 30m 12s",
},
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "OFFLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 19,
temperature: 100,
runtime: "30m",
},
{
name: "Localnode-3",
status: "ONLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 66,
temperature: 100,
runtime: "12h 30m 12s",
},
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "ONLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 79,
temperature: 100,
runtime: "12h 30m 12s",
},
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "ONLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 10,
temperature: 100,
runtime: "12h 30m 12s",
},
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "OFFLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 0,
temperature: 100,
runtime: "12h 30m 12s",
},
{
name: "XXXX-XXXX-XXXX-XXXX",
status: "ONLINE",
position: { lat: 40.7128, lng: 74.0012 },
battery: 56,
temperature: 100,
runtime: "12h 30m 12s",
},
],
};
},
};
</script>
<style scoped>
.table-container {
background-color: white;
padding: 0.5rem 1rem; /* Reduce top padding to 0.5rem */
margin: 0 auto; /* Remove margin at the top, keep it centered horizontally */
width: 100%; /* Full width of parent */
overflow-x: auto; /* Allow horizontal scroll if necessary */
}
.responsive-table {
width: 100%; /* Full width */
border-collapse: collapse; /* Ensure tight borders */
margin: 0; /* Remove margin at the top of the table */
table-layout: auto; /* Auto layout for slimmer columns */
}
.responsive-table th,
.responsive-table td {
padding: 0.5rem; /* Maintain slim padding */
text-align: center; /* Center text */
border-bottom: 1px solid #ddd;
}
.responsive-table th {
font-weight: bold;
}
.responsive-table tr:nth-child(even) {
background-color: #f9f9f9; /* Striped rows */
}
.status-online {
color: green;
font-weight: bold;
}
.status-offline {
color: red;
font-weight: bold;
}
</style>

View file

@ -0,0 +1,95 @@
<template>
<div>
<HeaderBar />
<div class="ma-8">
<div v-if="isPending">Loading...</div>
<ul v-else-if="data">
<li v-for="nodeGroup in data" :key="nodeGroup.groupId">
<CategoryContainer :nodeGroup="nodeGroup" />
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import HeaderBar from "./HeaderBar.vue";
import CategoryContainer from "./CategoryContainer.vue";
import { useQuery } from "@tanstack/vue-query";
import { axiosInstance } from "@/client";
import { NodeGroup } from "@/types";
import { search, key } from "@/store";
import MiniSearch from "minisearch";
import { computed, provide } from "vue";
const mockNodeGroups: NodeGroup[] = [
{
groupId: "group-1",
name: "Test Node Group 1",
nodes: [
{
uuid: "123e4567-e89b-12d3-a456-426614174000",
name: "Sensor Node A1",
status: 502,
coordla: 52.5200,
coordlong: 13.4050,
temperature: 22.5,
battery: 85,
runtime: 120,
},
{
uuid: "223e4567-e89b-12d3-a456-426614174001",
name: "Sensor Node A2",
status: 200,
coordla: 48.8566,
coordlong: 2.3522,
temperature: 20.0,
battery: 90,
runtime: 100,
},
]
},
];
const { isPending, isError, data, error } = useQuery({
queryKey: ["nodeGroups"],
queryFn: async () => {
//hier der API-Call für die Daten
return mockNodeGroups;
},
refetchInterval: 1 * 1,
});
const searchEngine = computed(() => {
const minisearch = new MiniSearch({
fields: ["name", "groupId"],
searchOptions: {
boost: { name: 2 },
prefix: true,
},
});
if (data.value) {
minisearch.addAll(data.value);
}
return minisearch;
});
const searching = computed(() => search.value !== "");
const visibleIds = computed(() => {
return searching.value ? searchEngine.value.search(search.value).map(result => result.groupId) : [];
});
provide(key, {
visibleIds,
searching,
});
</script>
<style scoped>
li,
ul {
list-style-type: none;
}
</style>