Skip to content
Snippets Groups Projects
Commit 5b3f315e authored by Vilde Min Vikan's avatar Vilde Min Vikan
Browse files

Merge branch 'createtrivio' into 'master'

CreateTrivio-View

See merge request !2
parents 6a41e572 a0f603f6
No related branches found
No related tags found
2 merge requests!8Updates to the history view,!2CreateTrivio-View
{
"hash": "8bbe2421",
"configHash": "994f273f",
"lockfileHash": "5ae3b81b",
"browserHash": "aa3147a0",
"optimized": {},
"chunks": {}
}
\ No newline at end of file
{
"type": "module"
}
......@@ -45,7 +45,7 @@
align-items: center;
width: 15vw;
height: 100vh;
height: 100%;
z-index: 1;
background-color: white;
......
......@@ -22,7 +22,9 @@ const toggleMenu = () => {
<input type="text" placeholder="Search..." v-model="searchQuery" @input="search">
</div>
<div class="top-items">
<router-link to="/homepage/create-trivio">
<img src="/src/components/icons/NewTrivio.png" alt="NewTrivio" width="40" height="40">
</router-link>
<img alt="Profile" src="../assets/user.svg" width="40" height="40" @click="toggleMenu">
<div v-if="isMenuOpen" class="curtain-menu">
<!-- Content of your curtain menu goes here -->
......
<script setup lang="ts">
import { ref, defineProps, defineEmits, watch } from 'vue'
const props = defineProps<{
index:number;
questionId:number;
}>();
const emit = defineEmits(['delete-question', 'save-question']);
const questionType = ref<string>('multiple');
const question = ref<string>('');
const answers = ref<Answer[]>([
{ answer: '', correct: false },
{ answer: '', correct: false },
{ answer: '', correct: false },
{ answer: '', correct: false}
]);
const tags = ref<Tag[]>([])
interface Answer {
answer: string;
correct: boolean;
}
interface Tag{
tag: String;
}
const addTag = () => {
tags.value.push({tag: ''})
};
const deleteTag = (index: number) => {
tags.value.splice(index, 1);
};
const deleteThisQuestion = () => {
emit('delete-question', props.questionId);
};
const updateCorrectness = (index: number) => {
answers.value.forEach((answer, i) => {
if (i !== index) {
answer.correct = false; // Set other answers to false
}
});
};
const preventSpace = (event: KeyboardEvent) => {
if (event.key === ' ') {
event.preventDefault();
}
};
const saveQuestionData = () => {
const questionData = {
questionId: props.questionId,
question: question.value,
questionType: questionType.value,
answers: answers.value,
tags: tags.value
};
emit('save-question', questionData);
};
watch(question, saveQuestionData);
watch(questionType, (newQuestionType) => {
if (newQuestionType === 'trueFalse') {
answers.value = [
{ answer: 'True', correct:false },
{ answer: 'False', correct:false }
]
} else {
answers.value = [
{ answer: '', correct:false },
{ answer: '', correct: false },
{ answer: '', correct:false },
{ answer: '', correct: false }
]
}
saveQuestionData(); // Save question data after updating answer values
});
watch(answers, saveQuestionData, { deep: true });
watch(tags, saveQuestionData, {deep: true});
</script>
<template>
<div class="trivio-question">
<div class="top">
<h2>{{index}}</h2>
<img alt="Profile" src="../components/icons/delete.png" width="25" height="25" @click="deleteThisQuestion">
</div>
<div class="input">
<div class="left">
<input type="text" v-model="question" placeholder="Question" class="question">
<template v-if="questionType === 'multiple'">
<div v-for="(answer, index) in answers" :key="index" class="answer-box">
<input type="checkbox" v-model="answer.correct" :id="'correct-answer-' + index">
<input type="text" v-model="answer.answer" :placeholder="'Answer ' + (index + 1)" class="answer">
</div>
</template>
<template v-else>
<div class="answer-box">
<input type="radio" :id="'true-answer' + questionId" :name="'answer-' + questionId" class="radio" v-model="answers[0].correct" value='true' @click="updateCorrectness(0)">
<label :for="'true-answer'+questionId" class="true-false"> True </label>
<input type="radio" :id="'false-answer' + questionId" :name="'answer-' + questionId" class="radio" v-model="answers[1].correct" value="true" @click="updateCorrectness(1)">
<label :for="'false-answer'+questionId" class="true-false"> False </label>
</div>
</template>
<div class="tag-section">
<button @click="addTag" class="addTag">Add Tag +</button>
<div class="tags">
<div v-for="(tag, index) in tags" :key="index" class="tag-box">
<input type="text" v-model="tag.tag" :placeholder="'Tag ' + (index + 1)" class="tag" @keypress="preventSpace">
<img src="@/components/icons/RemoveTag.png" alt="removeTag" @click="deleteTag(index)" width="20px" height="20px">
</div>
</div>
</div>
</div>
<div class="right">
<div class="question-type">
<h3>Question type:</h3>
<select v-model="questionType" class="box">
<option value="multiple">Multiple Choice</option>
<option value="trueFalse">True/False</option>
</select>
</div>
<div class="image-box">
<h1>Add image</h1>
<img src="/src/components/icons/AddImage.png" alt="Image" width="50px" height="50px">
</div>
</div>
</div>
</div>
</template>
<style scoped>
.trivio-question{
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 15px;
padding: 10px;
background-color: white;
}
.top{
display: flex;
flex-direction: row;
gap: 97%;
}
.input{
display: flex;
flex-direction: row;
gap: 10px;
}
.left{
display: flex;
flex-direction: column;
gap: 10px;
}
.question{
width: 100%;
height: 50px;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 20px;
padding: 10px;
}
.box{
height: 30px;
}
.answer-box{
width: 60vw;
display: flex;
flex-direction: row;
align-items: center;
place-items: center;
gap: 10px;
}
.answer{
width: 100%;
height: 50px;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 20px;
padding: 10px;
}
.radio {
margin-right: 2px;
}
.true-false{
width: 100%;
height: 50px;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 20px;
padding: 10px;
}
.tag-section{
display: flex;
flex-direction: row;
width: 100%;
gap: 15px;
}
.addTag{
height: 35px;
width: 94px;
font-size: medium;
}
.tags{
display: flex;
flex-wrap: wrap;
place-items: center;
align-items: center;
gap: 10px;
width: 90%;
}
.tag-box{
display: flex;
flex-direction: row;
align-items: center;
gap: 2px;
}
.tag{
width: 95px;
height: 35px;
border-radius: 5px;
border: 2px solid darkgray;
text-align: center;
font-size: medium;
}
.right{
display: flex;
flex-direction: column;
width: 100%;
gap: 10px;
}
.question-type{
height: 50px;
display: flex;
flex-direction: row;
align-items: center;
place-items: center;
gap: 10px;
}
.image-box{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 230px;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 12px;
color: darkgray;
padding: 10px;
gap: 10px;
}
</style>
src/components/icons/AddImage.png

7 KiB

src/components/icons/RemoveTag.png

1.08 KiB

src/components/icons/delete.png

12.3 KiB

......@@ -2,15 +2,13 @@ import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '@/views/frontpage/LoginView.vue'
import FrontPageView from '@/views/FrontPageView.vue'
import SignUpView from '@/views/frontpage/SignUpView.vue'
import MainPageView from '@/views/MainPageView.vue'
import ProfileView from '@/views/mainpage/ProfileView.vue'
import DiscoveryView from '@/views/mainpage/DiscoveryView.vue'
import MyTriviosView from '@/views/mainpage/MyTriviosView.vue'
import ContactView from '@/views/mainpage/ContactView.vue'
import HistoryView from '@/views/mainpage/HistoryView.vue'
import StartView from '@/views/mainpage/StartView.vue'
import PlayView from '@/views/mainpage/PlayView.vue'
import CreateTrivio from '@/views/mainpage/CreateTrivio.vue'
import MainPageView from '@/views/MainPageView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
......@@ -44,8 +42,12 @@ const router = createRouter({
component: ProfileView
},
{
path: 'discovery',
component: DiscoveryView
path: 'create-trivio',
component: CreateTrivio
},
{
path: 'home',
component: HomeView
},
{
path: 'trivios',
......
<script setup lang="ts">
import { ref, watch} from 'vue'
import TrivioQuestion from '@/components/TrivioQuestion.vue'
// Reactive variables
const title = ref<string>('')
const description = ref<string>('')
const difficulty = ref<string>('easy')
const category = ref<string>('random')
const visibility = ref<string>('private')
const questions = ref<Question[]>([])
const numberOfQuestions = ref<number[]>([])
const userID = 1
let uniqueComponentId = 0;
interface Answer {
answer: string;
correct: boolean;
}
interface Question {
questionId: number;
question: string;
questionType: string;
answers: Answer[]; // Adjust the type of inputFields as needed
tags: String[];
}
// Methods
const addQuestion = () => {
const newQuestionId = uniqueComponentId
numberOfQuestions.value.push(newQuestionId)
questions.value.push({
questionId: newQuestionId,
question: '',
questionType: '',
answers: [],
tags: []
})
uniqueComponentId ++;
console.log(uniqueComponentId)
}
const deleteQuestion = (questionId: number) => {
const index = questions.value.findIndex((q: Question) => q.questionId === questionId);
numberOfQuestions.value.splice(index, 1)
questions.value.splice(index,1)
}
const saveQuestion = (questionData: Question) => {
const index = questions.value.findIndex((q: Question) => q.questionId === questionData.questionId);
if (index !== -1) {
questions.value[index] = questionData;
console.log(questions)
} else {
questions.value.push(questionData);
console.log(questions.value.map(question => ({
question: question.question,
questionType: question.questionType,
answers: question.answers,
tags: question.tags
})))
}
};
watch(questions, (newQuestions) => {
console.log('All questions:', newQuestions)
})
const logInfo = () =>{
console.log(questions.value)
console.log(numberOfQuestions.value)
}
const saveQuizToBackend = async () => {
try {
const response = await fetch('http://localhost:8080/trivios/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"trivio": {
"title": title.value,
"description": description.value,
"difficulty": difficulty.value,
"visibility": visibility.value,
"multimedia_url": "cat.png"
},
"questionsWithAnswers": questions.value.map(question => ({
"question": {
"question": question.question,
"questionType": question.questionType,
"tags": question.tags.map(tag => tag.tag)
},
"answers": question.answers.map(answer => ({
"answer": answer.answer,
"correct": answer.correct
})),
})),
"userId": userID
})
});
// Quiz saved successfully, handle response if needed
const responseData = await response.text();
console.log('Quiz saved successfully:', responseData);
} catch (error:any) {
console.error('Error saving quiz:', error.message);
// Handle error, show error message to user, etc.
}
};
</script>
<template>
<div class="create-trivio">
<div class="header">
<h1 class="title">Create new quiz</h1>
<div class="options">
<h3>Difficulty: </h3>
<select v-model="difficulty" class="option">
<option value="easy">Easy</option>
<option value="medium">Medium</option>
<option value="hard">Hard</option>
</select>
<h3>Category: </h3>
<select v-model="category" class="option">
<option value="random">Random</option>
<option value="sport">Sport</option>
<option value="music">Music</option>
</select>
<h3>Visibility: </h3>
<select v-model="visibility" class="option">
<option value="private">Private</option>
<option value="public">Public</option>
</select>
</div>
<div class="buttons">
<button class="top-button" @click="logInfo">Save</button>
<button class="top-button" @click="saveQuizToBackend">Create</button>
</div>
</div>
<div class="input-boxes">
<div class="left">
<input type="text" v-model="title" placeholder="Enter title" class="trivio-title">
<textarea v-model="description" placeholder="Add description" class="description"></textarea>
</div>
<div class="right">
<div class="image-box">
<h1>Add image</h1>
<img src="/src/components/icons/AddImage.png" alt="Image" width="50px" height="50px">
</div>
</div>
</div>
<div class="questions">
<TrivioQuestion
v-for="(questionId, index) in numberOfQuestions"
:key="questionId"
:index="index+1"
:question-id="questionId"
@delete-question="deleteQuestion(questionId)"
@save-question="saveQuestion"
></TrivioQuestion>
</div>
<div class="add-box">
<button class="add-question" @click="addQuestion">
<img src="/src/components/icons/NewTrivio.png" alt="Image" width="50px" height="50px">
</button>
</div>
</div>
</template>
<style scoped>
.create-trivio{
display: flex;
flex-direction: column;
place-items: start;
width: 100%;
height: 100%;
padding: 20px;
gap:20px;
overflow-x: scroll;
background-color: rgba(196, 201, 220, 0.15);
}
.header{
display: flex;
flex-direction: row;
place-items: center;
align-items: center;
align-content: center;
width: 100%;
}
.title{
width: 30%;
font-weight: bold;
}
.options{
display: flex;
flex-direction: row;
place-content: center;
align-content: center;
place-items: center;
align-items: center;
gap: 10px;
}
.option{
width: 100px;
height: 30px;
}
.buttons{
display: flex;
flex-direction: row;
place-content: end;
align-content: center;
align-items: center;
gap: 20px;
width: 40%;
}
.top-button{
width: 150px;
height: 30px;
border-radius: 5px;
}
.left{
display: flex;
flex-direction: column;
place-items: start;
gap: 10px;
}
.input-boxes{
display: flex;
flex-direction: row;;
width: 100%;
gap: 10px;
}
.trivio-title{
width: calc(40vw - 2px); /* Subtracting border width from the width */
height: 50px;
border: 2px solid darkgray; /* Setting border instead of outline */
border-radius: 15px;
box-sizing: border-box;
font-size: 20px;
padding: 10px;
}
.description {
width: calc(40vw - 2px); /* Subtracting border width from the width */
height: 200px;
border: 2px solid darkgray; /* Setting border instead of outline */
border-radius: 15px;
box-sizing: border-box;
font-size: 15px;
padding: 10px;
resize: none;
}
.right{
width: 100%;
}
.image-box{
display: flex;
flex-direction: column;
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically */
width: 100%;
height: 262px;
border: 2px solid darkgray;
border-radius: 15px;
box-sizing: border-box;
font-size: 12px;
color: darkgray;
padding: 10px;
gap: 10px;
background-color: white;
}
.questions{
display: flex;
flex-direction: column;
gap: 20px;
width: 100%;
}
.add-box{
display: flex;
width: 100%;
align-content: center;
place-content: center;
}
.add-question{
border-radius: 50px;
}
</style>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment