<script setup> import { ref } from "vue"; import axios from "axios"; import Dropzone from "../components/Dropzone.vue"; import DropzoneLoading from "../components/DropzoneLoading.vue"; import Result from "../components/Result.vue"; const apiUrl = import.meta.env.VITE_BASE_URL || "http://127.0.0.1:8000"; const EXERCISES = ["squat", "plank", "bicep_curl", "lunge"]; const submitData = ref({ videoFile: null, exerciseType: null, }); const processedData = ref(null); const isProcessing = ref(false); const uploadToServer = async () => { if (!submitData.value.videoFile) { alert("No video selected"); return; } if (!submitData.value.exerciseType) { alert("No exercise type selected"); return; } processedData.value = null; try { isProcessing.value = true; const { data } = await axios.post( `${apiUrl}/api/video/upload?type=${submitData.value.exerciseType}`, { file: submitData.value.videoFile }, { headers: { "Content-Type": "multipart/form-data", }, } ); processedData.value = data; } catch (e) { console.error("Error: ", e); } finally { isProcessing.value = false; } }; </script> <template> <!-- Input section --> <section class="input-section"> <Dropzone v-show="!isProcessing" @file-uploaded="(file) => (submitData.videoFile = file)" /> <DropzoneLoading v-show="isProcessing" /> <div class="right-container"> <!-- exercises selection --> <div class="exercises-container"> <p class="exercise" v-for="exercise in EXERCISES" :class="{ active: submitData.exerciseType == exercise }" @click="submitData.exerciseType = exercise" > {{ exercise }} </p> </div> <button class="process-btn" @click="uploadToServer"> <span>Process!</span> </button> </div> </section> <!-- Results section --> <Result v-if="processedData" :data="processedData" /> </template> <style lang="scss" scoped> .input-section { display: flex; gap: 1rem; * { flex: 1; } .right-container { display: flex; flex-direction: column; width: 100%; .exercises-container { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: 1rem; .exercise { display: flex; justify-content: center; align-items: center; padding: 1rem 0; flex: 45%; color: var(--secondary-color); text-transform: uppercase; border: 3px solid var(--primary-color); border-radius: 0.3rem; cursor: pointer; transition: all 0.25s ease; &:hover { box-shadow: 0 6px 18px 0 rgba(#000, 0.1); transform: translateY(-6px); } &.active { background-color: var(--primary-color); font-weight: 700; } } } .process-btn { border: none; background-color: var(--primary-color); padding: 1.25rem 0; color: whitesmoke; font-size: 1.25rem; font-weight: 700; cursor: pointer; border-radius: 8px; transition: all 0.25s ease; &:hover { box-shadow: 0 6px 18px 0 rgba(#000, 0.1); color: var(--primary-color); border-color: transparent; background-color: transparent; } } } } </style>