Spaces:
Configuration error
Configuration error
| <script setup> | |
| import { ref, computed } from "vue"; | |
| import Video from "./Video.vue"; | |
| const { data } = defineProps(["data"]); | |
| const summaryData = computed(() => { | |
| let results = { | |
| total: 0, | |
| totalInString: "", | |
| details: {}, | |
| }; | |
| let totalErrors = data.details.length; | |
| results.total = totalErrors; | |
| if (totalErrors == 0 || totalErrors == 1) | |
| results.totalInString = `${totalErrors} error`; | |
| else results.totalInString = `${totalErrors} errors`; | |
| data.details.forEach((error) => { | |
| let stage = error.stage; | |
| results.details[stage] = results.details[stage] | |
| ? results.details[stage] + 1 | |
| : 1; | |
| }); | |
| return results; | |
| }); | |
| const selectedDisplay = ref("summary"); | |
| const videoStart = ref(0); | |
| const jumpToVideoLocation = (second) => { | |
| selectedDisplay.value = "video"; | |
| videoStart.value = second; | |
| }; | |
| </script> | |
| <template> | |
| <section class="result-section"> | |
| <!-- Navigators --> | |
| <ul class="tab-links"> | |
| <li | |
| :class="{ active: selectedDisplay == 'summary' }" | |
| @click="() => (selectedDisplay = 'summary')" | |
| > | |
| Summary | |
| </li> | |
| <li | |
| :class="{ active: selectedDisplay == 'detail' }" | |
| @click="() => (selectedDisplay = 'detail')" | |
| > | |
| Detail | |
| </li> | |
| <li | |
| :class="{ active: selectedDisplay == 'video' }" | |
| @click="() => (selectedDisplay = 'video')" | |
| > | |
| Full Video | |
| </li> | |
| </ul> | |
| <!-- Contents --> | |
| <div class="tab-container"> | |
| <!-- Summary content --> | |
| <template v-if="selectedDisplay == 'summary'"> | |
| <!-- Display Counter or other information --> | |
| <p class="main" v-if="data.counter"> | |
| <span class="info-color" v-if="data.type != 'bicep_curl'"> | |
| Counter: {{ data.counter }} | |
| </span> | |
| <span class="info-color" v-else> | |
| Left arm counter: {{ data.counter.left_counter }} - | |
| Right arm counter: {{ data.counter.right_counter }} | |
| </span> | |
| </p> | |
| <!-- Display error --> | |
| <p class="main"> | |
| There are | |
| <span class="error-color"> | |
| {{ summaryData.totalInString }} | |
| </span> | |
| found. | |
| <!-- Icon --> | |
| <i | |
| class="fa-solid fa-circle-exclamation error-color" | |
| v-if="summaryData.total > 0" | |
| ></i> | |
| <i class="fa-solid fa-circle-check" v-else></i> | |
| </p> | |
| <ul class="errors" v-if="summaryData.total > 0"> | |
| <li v-for="(total, error) in summaryData.details"> | |
| <i class="fa-solid fa-caret-right"></i> | |
| {{ error }}: {{ total }} | |
| </li> | |
| </ul> | |
| </template> | |
| <!-- Detail Content --> | |
| <KeepAlive> | |
| <template v-if="selectedDisplay == 'detail'"> | |
| <div | |
| class="box-error" | |
| v-for="(error, index) in data.details" | |
| > | |
| <p> | |
| {{ index + 1 }}. {{ error.stage }} at | |
| <span | |
| class="error-time" | |
| @click="jumpToVideoLocation(error.timestamp)" | |
| > | |
| {{ error.timestamp }} second | |
| </span> | |
| </p> | |
| <img :src="`${error.frame}`" /> | |
| <hr /> | |
| </div> | |
| </template> | |
| </KeepAlive> | |
| <!-- Full Video content --> | |
| <KeepAlive> | |
| <template v-if="selectedDisplay == 'video'"> | |
| <div class="video-container"> | |
| <Video | |
| :video-name="data.file_name" | |
| :start-at="videoStart" | |
| ></Video> | |
| </div> | |
| </template> | |
| </KeepAlive> | |
| </div> | |
| </section> | |
| </template> | |
| <style lang="scss" scoped> | |
| .result-section { | |
| margin-top: 2rem; | |
| margin-bottom: 5rem; | |
| .tab-links { | |
| display: flex; | |
| li { | |
| width: 6em; | |
| padding: 0.75rem 1rem; | |
| padding-right: 1.2rem; | |
| background-color: rgb(180, 179, 179); | |
| border-top-left-radius: 1rem; | |
| border-top-right-radius: 1rem; | |
| font-size: 1rem; | |
| text-transform: uppercase; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| &.active { | |
| background-color: var(--primary-color); | |
| } | |
| &:hover { | |
| background-color: rgba($color: #41b883, $alpha: 0.4); | |
| } | |
| } | |
| } | |
| .tab-container { | |
| padding: 1rem 2rem; | |
| border: 3px solid var(--primary-color); | |
| p.main { | |
| font-size: 1.5rem; | |
| margin: 1rem 0; | |
| i { | |
| font-size: 1.5rem; | |
| } | |
| } | |
| ul.errors { | |
| li { | |
| margin: 0.75rem 0; | |
| font-size: 1.2rem; | |
| text-transform: capitalize; | |
| i { | |
| margin-right: 1rem; | |
| } | |
| } | |
| } | |
| .box-error { | |
| margin-bottom: 2rem; | |
| p { | |
| font-size: 1.2rem; | |
| text-transform: capitalize; | |
| margin-bottom: 0.5rem; | |
| } | |
| img { | |
| width: 500px; | |
| } | |
| span.error-time { | |
| color: rgb(85, 149, 171); | |
| cursor: pointer; | |
| } | |
| hr { | |
| background-color: var(--primary-color); | |
| color: var(--primary-color); | |
| } | |
| } | |
| .video-container { | |
| width: 80%; | |
| margin-inline: auto; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| } | |
| .error-color { | |
| color: red; | |
| } | |
| .info-color { | |
| color: rgb(55, 194, 55); | |
| } | |
| } | |
| </style> | |