Skip to content
Snippets Groups Projects

Added new and updated methods for trivio retrieval from new and updated method...

Merged Vilde Min Vikan requested to merge updateMethods into master
4 files
+ 486
415
Compare changes
  • Side-by-side
  • Inline
Files
4
+ 344
0
<script setup lang="ts">
import TrivioCard from "@/components/TrivioCard.vue";
import router from "@/router";
import {getPicture, getTriviosByUser, getTriviosByOtherUser} from "@/utils/httputils";
import {useTokenStore} from "@/stores/token";
import { defineProps, onMounted, ref, watch } from 'vue'
const tokenStore = useTokenStore()
//data-components
const trivios = ref(null);
const trivioBlobUrls = ref(new Map()); // Store blob URLs for each trivio
//filters-components
const tags = ref<Tag[] | null>(null)
const difficulty = ref<string | null>(null)
const category = ref<string | null>(null)
//page-orientation
let page = 0;
let pages = 0;
let currentPage = 0;
const props = defineProps<{
fetchMethod: Function,
title: String,
}>();
interface Tag{
tag: string;
}
onMounted(async () => {
try{
page = 0;
difficulty.value = null;
category.value = null;
tags.value = null;
await fetchTrivios();
await fetchBlobUrls();
}catch (error){
console.log(error)
}
});
const goToPage = (pageNumber: number) => {
if (pageNumber >= 0 && pageNumber < pages) {
page = pageNumber;
fetchTrivios();
}
};
const nextPage = () => {
if (page < pages-1) {
page ++;
fetchTrivios();
}
};
const previousPage = () => {
if (page > 0) {
page--;
fetchTrivios();
}
};
const fetchTrivios = (async () => {
try {
const response = await props.fetchMethod(tokenStore.jwtToken, page, 10, category.value, difficulty.value, tags.value);
if(response){
try {
const { content, totalPages, number } = response.data; // Extract pagination data
trivios.value = content;
pages= totalPages;
currentPage = number;
} catch (error){
console.log('The response do not contain trivios')
}
} else{
console.log('Response is undefined!')
}
} catch (error){
console.log('Error fetching trivios', error)
}
});
const fetchBlobUrls = async () => {
if (trivios.value) {
for (const trivio of trivios.value) {
const blobUrl = await getBlobUrl(trivio.multimedia_url);
trivioBlobUrls.value.set(trivio.id, blobUrl); // Store blob URL in the map with trivio ID as key
}
} else {
console.log('Value of trivios is null!')
}
};
const getBlobUrl = async (multimediaUrl: string) => {
if (!multimediaUrl) return "";
try {
return await getPicture(multimediaUrl, tokenStore.jwtToken);
} catch (error) {
console.error("Error fetching blobUrl:", error);
return "";
}
};
const handleCardClick = (id: number) => {
try {
console.log('Clicked TrivioCard with ID:', id);
router.push({ name: 'start', params: { id } })
} catch (error){
console.error('Issues routing to trivio', error)
}
};
//Add an empty tag
const addTag = () => {
if(tags.value) {
tags.value.push({ tag: '' })
} else{
tags.value = []
tags.value.push({tag: ''})
}
};
//Remove an existing tag
const deleteTag = (index: number) => {
if(tags.value){
tags.value.splice(index, 1);
if(tags.value.length != 0){
fetchTrivios();
} else {
tags.value = null
fetchTrivios();
}
} else {
console.error('Issues removing tag')
}
};
//Prevent space in a tag
const preventSpace = (event: KeyboardEvent) => {
if (event.keyCode === 32) {
event.preventDefault();
}
};
watch(category, fetchTrivios);
watch(difficulty, fetchTrivios);
</script>
<template>
<div class="MyTrivios">
<div class="FilterOptions">
<h3>Category: </h3>
<select v-model="category" class="option">
<option :value="null">Category</option>
<option value="Random">Random</option>
<option value="Sport">Sport</option>
<option value="Music">Music</option>
</select>
<h3>Difficulty: </h3>
<select v-model="difficulty" class="option">
<option :value="null">Difficulty</option>
<option value="Easy">Easy</option>
<option value="Medium">Medium</option>
<option value="Hard">Hard</option>
</select>
</div>
<h1>{{props.title}}</h1>
<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"
@keypress.enter="fetchTrivios">
<img src="@/components/icons/RemoveTag.png" alt="removeTag" @click="deleteTag(index)" width="20px" height="20px">
</div>
</div>
</div>
<div class="card-container">
<TrivioCard
v-for="(trivio, index) in trivios"
:key="index"
:title="trivio.title"
:category="trivio.category"
:image="trivio.image"
:username="trivio.user.username"
:number-of-question="trivio.questionList.length"
:id="trivio.id"
:difficulty="trivio.difficulty"
:media="trivioBlobUrls.get(trivio.id)"
@click="handleCardClick(trivio.id)"
></TrivioCard>
</div>
<div class="pagination">
<button @click="previousPage" :disabled="currentPage === 0">Previous</button>
<div v-if="pages>0" class="page-numbers">
<button
v-for="pageNumber in pages"
:key="pageNumber-2"
@click="goToPage(pageNumber-1)"
:class="{ active: pageNumber-1 === currentPage }"
>{{ pageNumber}}</button>
</div>
<button @click="nextPage" :disabled="currentPage === pages - 1">Next</button>
</div>
</div>
</template>
<style scoped>
.MyTrivios{
display: flex;
flex-direction: column;
padding: 20px;
height: 100%;
width: 100%;
}
h1 {
color: #5E5CE5;
}
.FilterOptions{
display: flex;
flex-direction: row;
width: 100%;
place-items: center;
place-content: start;
gap: 10px;
}
.card-container {
display: flex;
flex-wrap: wrap;
width: 100%;
column-gap: 20px;
}
.tag-section{
display: flex;
flex-direction: row;
width: 100%;
gap: 15px;
}
.addTag{
height: 30px;
width: 100px;
font-size: medium;
}
.tags{
display: flex;
flex-wrap: wrap;
place-items: center;
align-items: center;
gap: 10px;
max-width: 90%;
}
.tag-box{
display: flex;
flex-direction: row;
align-items: center;
gap: 2px;
}
.tag{
width: 100px;
height: 30px;
border-radius: 5px;
border: 2px solid darkgray;
text-align: center;
font-size: medium;
}
.option{
width: 100px;
height: 30px;
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
.pagination button {
padding: 5px 10px;
margin: 0 5px;
border: 1px solid #ccc;
border-radius: 3px;
background-color: transparent;
cursor: pointer;
}
.pagination button:hover {
background-color: #f0f0f0;
}
.pagination button:disabled {
color: #ccc;
cursor: not-allowed;
}
.page-numbers {
display: flex;
}
.page-numbers button {
padding: 5px 10px;
margin: 0 2px;
border: 1px solid #ccc;
border-radius: 3px;
background-color: transparent;
cursor: pointer;
}
.page-numbers button.active {
background-color: #5E5CE5;
color: white;
}
.page-numbers button:hover {
background-color: #f0f0f0;
}
.page-numbers button:disabled {
color: #ccc;
cursor: not-allowed;
}
</style>
Loading