<template> <div class="minion"> <span class="name">{{ name }}</span> <span class="ip">{{ ip }}</span> Temperature: {{ temperature }} </div> </template> <script lang="ts"> import { ref, defineComponent } from "vue"; interface MinionResponseData { data: { temperature: number } | null, error: string | null } export default defineComponent( { name: "MinionStatus", props: { name: { type: String, required: true }, ip: { type: String, required: true } }, setup(props) { const temperature = ref("None"); async function fetch_temperature() { let response: Response; try { response = await fetch(`http://${props.ip}`); } catch (err) { const error = err as Error; console.error( `Failed to fetch temperature for minion "${props.name}". ` + `${error.message}` ); return; } const data = await response.json() as MinionResponseData; if(!response.ok) { if(data.error !== null) { console.error( `Minion "${props.name}" responded with status ` + `${response.status} and error "${data.error}"` ); } else { console.error( `Minion "${props.name}" responded with status ` + `${response.status} and a unknown error` ); } return; } if(data.data == null) { console.error(`Minion "${props.name}" has no data in response`); return; } temperature.value = `${data.data.temperature}°C`; } return { temperature, fetch_temperature }; }, created() { this.fetch_temperature(); } } ); </script> <style scoped lang="scss"> @use "@/scss/colors"; .minion { background-color: lighten(colors.$background, 8%); width: fit-content; padding-top: 1em; padding-bottom: 1.5em; padding-left: 1.5em; padding-right: 3em; border: 1px solid lighten(colors.$background, 14%); border-radius: 8px; .name { display: block; font-size: 1.25rem; font-weight: 700; color: colors.$primary; margin-bottom: 0.25em; } .ip { display: block; } } </style>