diff --git a/FullstackProsjekt/src/frontend/src/assets/Svg.vue b/FullstackProsjekt/src/frontend/src/assets/Svg.vue index b12767bce8e5d5fc5b80d5b0e6429f512b7a24c8..19ee54b57c013388d9eac5890b5a3433a7345eee 100644 --- a/FullstackProsjekt/src/frontend/src/assets/Svg.vue +++ b/FullstackProsjekt/src/frontend/src/assets/Svg.vue @@ -18,8 +18,8 @@ const icon = defineAsyncComponent(()=> <style> .icon{ - height: 20px; - width: 20px; + height: 25px; + width: 25px; display: inline-block; background-size: contain; background-repeat: no-repeat; diff --git a/FullstackProsjekt/src/frontend/src/assets/main.css b/FullstackProsjekt/src/frontend/src/assets/main.css index ac47402ed38330b853ec19efc81bfb62ca14ba0a..f650802950753632d91263426017b3b42d4eaf5a 100644 --- a/FullstackProsjekt/src/frontend/src/assets/main.css +++ b/FullstackProsjekt/src/frontend/src/assets/main.css @@ -9,7 +9,6 @@ input { padding: 5px; border-radius: 5px; border: none; - min-width: 220px; background-color: #E5E5E5; margin-bottom: 10px; font-family: monospace; @@ -23,10 +22,17 @@ label { font-weight: bold; } +select{ + font-family: monospace; +} + + + .space{ margin: 90px; } +/* Other */ .row{ margin-top: 5%; display: flex; @@ -46,7 +52,13 @@ label { .course-col:hover{ box-shadow: 0 0 20px 0px rgba(0,0,0,0.3); } +.go-back-section{ + padding-top: 5vh; + padding-left: 5vh; +} + +/* ERROR HANDLE */ .error-message{ color: #e53a1c; padding: 10px; @@ -54,6 +66,8 @@ label { margin-bottom: 20px; } + +/* BUTTONS */ .play-btn{ padding: 10px; text-decoration: none; @@ -121,7 +135,6 @@ label { margin-left: 10px; cursor: pointer; } - .submit-btn{ background-color: #CCA43B; font-size: 20px; @@ -142,6 +155,9 @@ label { color: white; } + + + @media (max-width: 700px){ .row{ flex-direction: column; diff --git a/FullstackProsjekt/src/frontend/src/components/shared/create-quiz/CreateQuizView.vue b/FullstackProsjekt/src/frontend/src/components/shared/create-quiz/CreateQuizView.vue new file mode 100644 index 0000000000000000000000000000000000000000..e6512e2c9c8f1ea37d9cfe60cc7a294f2eb69278 --- /dev/null +++ b/FullstackProsjekt/src/frontend/src/components/shared/create-quiz/CreateQuizView.vue @@ -0,0 +1,131 @@ +<script> +import router from "@/router/index.js"; +import {apiClient} from "@/api.js"; +import {getIdByToken} from "@/tokenController.js"; +import {categoryEnums} from "@/data/categories.js" +import {difficultyEnums} from "@/data/difficulties.js"; +import Svg from "@/assets/Svg.vue"; + +//like editquiz, but w/o questions, redirect to edit when quiz is constructed + +export default { + components: {Svg}, + data() { + return { + showNewQuestion: false, + creatorId: null, + quiz: null, + quizId: null, + quizTitle: '', + category: '', + difficulty: '', + errorMsg: '', + selectedCategory: null, + categories: categoryEnums, + selectedDifficulty: null, + difficulties: difficultyEnums, + //TODO: make quiz object + }; + }, + mounted() { + this.getUser(); + }, + methods: { + async constructQuiz() { + try { + const post = { + title: this.quizTitle, + creatorId: this.creatorId, + category: this.selectedCategory, + difficulty: this.selectedDifficulty + } + await apiClient.post('quiz/create', post).then(response => { + this.quizId = JSON.parse(response.data.id); + router.push({name: 'editQuiz', params: {quizId: this.quizId}}); + }) + } catch(error){ + this.errorMsg = 'Cannot construct quiz'; + } + }, + async getUser() { + this.creatorId = await getIdByToken(); + } + }, +} +</script> + +<template> + <body> + <router-link to="/overviewQuiz" ><Svg name="go-back-icon" class="go-back-section"/></router-link> + + <div class="new-quiz-page"> + <form @submit.prevent="constructQuiz"> + <div class="newQuizDiv"> + <h1>New quiz</h1> + <div> + <h2>Title</h2> + <input type="text" required v-model="quizTitle" placeholder="Insert title here..."/> <br> + </div> + <div> + <h2>Category</h2> + <form> + <select v-model="selectedCategory"> + <option v-for="category in categories" :key="category" :value="category">{{ category }}</option> + </select> + </form> + </div> + <div> + <h2>Difficulty</h2> + <form> + <select v-model="selectedDifficulty"> + <option v-for="difficulty in difficulties" :key="difficulty" :value="difficulty">{{ difficulty}}</option> + </select> + </form> + </div> + <div class="space"/> + + <div> + <button class="submit-btn">Submit</button> + </div> + + </div> + </form> + + + </div> + </body> + +</template> +<style> +.new-quiz-page { + margin: 5vh auto; + max-width: 400px; + padding: 0 20px; +} + +input, +select { + width: 100%; + height: 40px; + margin-bottom: 10px; + background-color: #E5E5E5; + border: 1px solid transparent; + border-radius: 5px; + padding: 5px; + box-sizing: border-box; +} + +select { + appearance: none; + background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M7 10l5 5 5-5H7z"/></svg>'); + background-repeat: no-repeat; + background-position-x: calc(100% - 8px); + background-position-y: 50%; + padding-right: 20px; +} + +.submit-btn { + display: block; + margin: 0 auto; +} +</style> diff --git a/FullstackProsjekt/src/frontend/src/views/EditQuizView.vue b/FullstackProsjekt/src/frontend/src/components/shared/create-quiz/EditQuizView.vue similarity index 100% rename from FullstackProsjekt/src/frontend/src/views/EditQuizView.vue rename to FullstackProsjekt/src/frontend/src/components/shared/create-quiz/EditQuizView.vue diff --git a/FullstackProsjekt/src/frontend/src/components/shared/QuizCard.vue b/FullstackProsjekt/src/frontend/src/components/shared/create-quiz/QuizCard.vue similarity index 100% rename from FullstackProsjekt/src/frontend/src/components/shared/QuizCard.vue rename to FullstackProsjekt/src/frontend/src/components/shared/create-quiz/QuizCard.vue diff --git a/FullstackProsjekt/src/frontend/src/router/index.js b/FullstackProsjekt/src/frontend/src/router/index.js index 8db72f9b55f9041b3f453c3686c6a4ba762ec820..97567eafea7dcfd2b37885eea3873ac727f902c0 100644 --- a/FullstackProsjekt/src/frontend/src/router/index.js +++ b/FullstackProsjekt/src/frontend/src/router/index.js @@ -1,6 +1,6 @@ import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' -import EditQuizView from "@/views/EditQuizView.vue"; +import EditQuizView from "@/components/shared/create-quiz/EditQuizView.vue"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -35,16 +35,16 @@ const router = createRouter({ name: 'signup', component: () => import('../views/SignupView.vue') }, - { - path: '/createQuiz', - name: 'create Quiz', - component: () => import('../views/NewQuizView.vue') - }, { path: '/overviewQuiz', name: 'overview Quiz', component: () => import('../views/OverviewQuizView.vue') }, + { + path: '/create-quiz', + name: 'create Quiz', + component: () => import('../components/shared/create-quiz/CreateQuizView.vue') + }, { path: '/play-quiz/:quizId', name: 'playQuiz', diff --git a/FullstackProsjekt/src/frontend/src/views/NewQuizView.vue b/FullstackProsjekt/src/frontend/src/views/NewQuizView.vue deleted file mode 100644 index 71d971370489da54de7d4627fdd65cdde3ba214e..0000000000000000000000000000000000000000 --- a/FullstackProsjekt/src/frontend/src/views/NewQuizView.vue +++ /dev/null @@ -1,142 +0,0 @@ -<script> -import { ref, onMounted } from 'vue'; -import { useRoute } from 'vue-router'; -import router from "@/router/index.js"; -import {apiClient} from "@/api.js"; -import {getIdByToken} from "@/tokenController.js"; -import {categoryEnums} from "@/data/categories.js" -import {difficultyEnums} from "@/data/difficulties.js"; - -//like editquiz, but w/o questions, redirect to edit when quiz is constructed - -export default { - data() { - return { - showNewQuestion: false, - creatorId: null, - quiz: null, - quizId: null, - quizTitle: '', - category: '', - difficulty: '', - errorMsg: '', - selectedCategory: null, - categories: categoryEnums, - selectedDifficulty: null, - difficulties: difficultyEnums, - //TODO: make quiz object - }; - }, - mounted() { - this.getUser(); - }, - methods: { - async constructQuiz() { - try { - const post = { - title: this.quizTitle, - creatorId: this.creatorId, - category: this.selectedCategory, - difficulty: this.selectedDifficulty - } - await apiClient.post('quiz/create', post).then(response => { - this.quizId = JSON.parse(response.data.id); - router.push({name: 'editQuiz', params: {quizId: this.quizId}}); - }) - } catch(error){ - this.errorMsg = 'Cannot construct quiz'; - } - }, - async getUser() { - this.creatorId = await getIdByToken(); - } - }, -} -</script> - -<template> - <body> - <form @submit.prevent="constructQuiz"> - <div class="newQuizDiv"> - <router-link to="/overviewQuiz"> <- </router-link> - <h1>New quiz</h1> - <div> - <h2>Title</h2> - <input type="text" required v-model="quizTitle" placeholder="Insert title here..."/> <br> - </div> - <div> - <h2>Category</h2> - <form> - <select v-model="selectedCategory"> - <option v-for="category in categories" :key="category" :value="category">{{ category }}</option> - </select> - </form> - </div> - <div> - <h2>Difficulty</h2> - <form> - <select v-model="selectedDifficulty"> - <option v-for="difficulty in difficulties" :key="difficulty" :value="difficulty">{{ difficulty}}</option> - </select> - </form> - </div> - <!-- - <div class="question-table"> - <table class="table"> - <thead> - <tr> - <th scope="col">#</th> - <th scope="col">Question</th> - <th scope="col">Action</th> - </tr> - </thead> - <tbody> - <tr> - <th scope="row">1</th> - <td>What is Vue?</td> - <td> - <button class="play-btn">View</button> - <button class="edit-btn">Edit</button> - <button class="delete-btn"> Delete</button> - </td> - </tr> - - <div class="footer"> - <router-link to="/overviewQuiz" class="delete-btn"> Cancel </router-link> - <button class="submit-btn" type="submit"> Submit</button> - </div> - </form> - </div> - </body> - -</template> - -<style> -.new-quiz-page{ - margin:20vh; -} - -input{ - height: 25px; - width: 100%; -} -select{ - min-width: 100%; - height: 25px; - background-color: #E5E5E5; - border-color: transparent; - border-radius: 5px; -} - -.footer { - margin: 10vh; - display: flex; - justify-content: center; - align-items: center; -} - -.delete-btn { - margin-right: 20px; -} - -</style> \ No newline at end of file diff --git a/FullstackProsjekt/src/frontend/src/views/OverviewQuizView.vue b/FullstackProsjekt/src/frontend/src/views/OverviewQuizView.vue index b5af25c5c0a9ca9fae11051e27cfc71c1af23962..3ce325dc7a6aaadb90dfa8cdf0b11ac17693f6ff 100644 --- a/FullstackProsjekt/src/frontend/src/views/OverviewQuizView.vue +++ b/FullstackProsjekt/src/frontend/src/views/OverviewQuizView.vue @@ -8,7 +8,7 @@ <h1>Your quizzes</h1> <p>Select a quiz for your creation to either play, edit or delete</p> </div> - <router-link to="/createQuiz" class="add-Btn">New quiz</router-link> + <router-link to="/create-quiz" class="add-Btn">New quiz</router-link> </div> <div class="row"> @@ -17,90 +17,14 @@ </div> </div> - <!-- - <div class="question-table"> - <table class="table"> - <thead> - <tr> - <th scope="col">#</th> - <th scope="col">Question</th> - <th scope="col">Action</th> - </tr> - </thead> - <tbody> - <tr> - <th scope="row">1</th> - <td>What is Vue?</td> - <td> - <button class="play-btn">View</button> - <button class="edit-btn">Edit</button> - <button class="delete-btn"> Delete</button> - </td> - </tr> - - </tbody> - </table> - - - - <Teleport to="body"> - <NewQuestionModel :show="showNewQuestionModal" @close="destroyModal"> - - <template #header> - <h5> Add New Question</h5> - </template> - - <template #body> - <form> - <div class="mb-3"> - <label for="question" class="form-label">Question</label> <br> - <input type="text" v-model="createdQuestion" class="form-control" id="questionInput"> - </div> - <table class="table"> - <thead> - <tr> - <th scope="col">#</th> - <th scope="col">Answer</th> - <th scope="col">Correct ?</th> - </tr> - </thead> - <tbody> - <tr v-for="(answer, index) in newAnswers"> - <th scope="row">{{answer.id}}</th> - <td> - <input type="text" v-model="answer.answer" id="questionInput"> - </td> - <td> - <input :checked="answer.correct_answer === 1" class="form-check-input" :value="answer.id" @change="handleRadioToggle(answer.id)" type="radio"> - </td> - </tr> - </tbody> - </table> - </form> - </template> - - <template #footer> - <button @click="addNewAnswers" class="add-Btn" v-if="newAnswers.length<4" >+</button> - <button @click="destroyModal" class="close-btn"> Close</button> - <button v-if="newAnswers.length>=2" @click="submitQuestion" class="submit-btn">Submit</button> - </template> - - </NewQuestionModel> - </Teleport> - </div> - - --> - </div> </body> </template> <script> -import QuizCard from "@/components/shared/QuizCard.vue"; +import QuizCard from "@/components/shared/create-quiz/QuizCard.vue"; import {getIdByToken} from "@/tokenController.js"; import {apiClient} from "@/api.js"; -import NewQuestionModel from "@/components/shared/NewQuestionModel.vue"; - export default { components: {