Files
Eurovision-25-frontend/pages/review/[id].vue
T

207 lines
6.6 KiB
Vue

<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
interface Review {
song_id: number
user_id: number
score_song: number
score_show: number
score_costume: number
review_text: string
created_at: string
updated_at: string
}
const config = useRuntimeConfig()
const apiBase = config.public.apiBase
const route = useRoute()
const { id } = route.params
// Initialize reactive data
const artist = ref(null)
const review = ref<Review>({})
const showOriginalLyrics = ref(false)
const showTranslationLyrics = ref(false)
// Form data
const song = ref(50)
const show = ref(50)
const costume = ref(50)
const textReview = ref('')
// Get user from localStorage
const user = ref(null)
// Initialize user data from localStorage on client side only
onMounted(() => {
if (process.client) {
const userData = localStorage.getItem('user')
if (userData) {
user.value = JSON.parse(userData)
}
}
})
// Functions to toggle lyrics visibility
function toggleOriginalLyrics() {
showOriginalLyrics.value = !showOriginalLyrics.value
}
function toggleTranslationLyrics() {
showTranslationLyrics.value = !showTranslationLyrics.value
}
// Form submission function
function submitReview() {
const payload = {
song_id: id,
user_id: user.value?.id,
score_song: song.value,
score_show: show.value,
score_costume: costume.value,
text_review: text_review.value
}
// Implement your review submission logic here
console.log('Review submitted with data:', payload)
const response = fetch(`${apiBase}/reviews/`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
}
// Fetch artist data based on ID
onMounted(async () => {
try {
// Fetch song data
const response = await fetch(`${apiBase}/songs/${id}`)
artist.value = await response.json()
} catch (error) {
console.error('Error fetching artist data:', error)
}
// Get user from localStorage and then fetch reviews if user exists
if (process.client) {
const userData = localStorage.getItem('user')
if (userData) {
user.value = JSON.parse(userData)
// Now fetch reviews with the user ID
try {
const response = await fetch(`${apiBase}/reviews/?song_id=${id}&user_id=${user.value.id}`)
review.value = await response.json()
// If there's existing review data, populate the form
if (review.value) {
song.value = review.value.score_song || 0
show.value = review.value.score_show || 0
costume.value = review.value.score_costume || 0
textReview.value = review.value.text_review || ''
}
} catch (error) {
console.error('Error fetching review data:', error)
}
}
}
})
</script>
<template>
<div v-if="artist" class="space-y-4">
<div>
<h1 class="text-2xl font-bold text-center">{{ artist.artist }}</h1>
<p class="text-center italic">{{ artist.title }}</p>
</div>
<img class="w-1/2 mx-auto" :src="artist.img" alt="">
<div>
<h2
@click="toggleOriginalLyrics"
class="cursor-pointer hover:text-blue-600 flex items-center"
>
Sanat
<span class="ml-2 text-sm">
{{ showOriginalLyrics ? '▼' : '►' }}
</span>
</h2>
<pre v-show="showOriginalLyrics" class="lyricsFont transition-all duration-300">{{ artist.lyrics_original }}</pre>
</div>
<div v-if="artist.lyrics_translation_fi">
<h2
@click="toggleTranslationLyrics"
class="cursor-pointer hover:text-blue-600 flex items-center"
>
Käännös
<span class="ml-2 text-sm">
{{ showTranslationLyrics ? '▼' : '►' }}
</span>
</h2>
<pre v-show="showTranslationLyrics" class="lyricsFont transition-all duration-300">{{ artist.lyrics_translation_fi }}</pre>
</div>
<ul class="flex flex-wrap justify-center list-none gap-2 p-0 m-0">
<li class="tag" v-for="tag in artist.tags" :key="tag">{{ tag }}</li>
</ul>
<form @submit.prevent="submitReview" class="space-y-4 flex flex-col gap-4">
<div class="flex flex-col gap-2">
<label for="slider-song">Kappale</label>
<input id="slider-song" type="range" min="1" max="100" v-model="song"/>
<div class="flex justify-between"><p>0</p><p class="sliderSeparator">|</p><p>25</p><p class="sliderSeparator">|</p><p>50</p><p class="sliderSeparator">|</p><p>75</p><p class="sliderSeparator">|</p><p>100</p></div>
</div>
<div class="flex flex-col gap-2">
<label for="slider-show">Lava show</label>
<input id="slider-show" type="range" min="1" max="100" v-model="show"/>
<div class="flex justify-between"><p>0</p><p class="sliderSeparator">|</p><p>25</p><p class="sliderSeparator">|</p><p>50</p><p class="sliderSeparator">|</p><p>75</p><p class="sliderSeparator">|</p><p>100</p></div>
</div>
<div class="flex flex-col gap-2">
<label for="slider-costume">Asuste</label>
<input id="slider-costume" type="range" min="1" max="100" v-model="costume"/>
<div class="flex justify-between"><p>0</p><p class="sliderSeparator">|</p><p>25</p><p class="sliderSeparator">|</p><p>50</p><p class="sliderSeparator">|</p><p>75</p><p class="sliderSeparator">|</p><p>100</p></div>
</div>
<div class="flex flex-col gap-2">
<label for="text_review">Arvostelu (vaihtoehtoinen)</label>
<textarea id="text_review" placeholder="Arvostelu" class="textfield" v-model="textReview"/>
</div>
<button type="submit" class="btn-primary">Arvostele</button>
</form>
</div>
<div v-else>
<h1>Artist not found</h1>
</div>
</template>
<style>
.tag {
display: inline-block;
padding: 2px 6px;
background-color: #ccc;
margin: 2px;
border-radius: 6px;
font-size: 0.8rem;
}
.lyricsFont {
font-family: Arial, Helvetica, sans-serif;
font-size: 0.8rem;
text-align: center;
}
.textfield {
border: none;
border-bottom: 1px solid #ccc;
width: 100%; /* Changed from max-width: 80% to width: 100% */
padding: 6px;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 6px;
}
</style>