Add artist review page and components with basic layout and styling
This commit is contained in:
+18
-1
@@ -1 +1,18 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss";
|
||||
|
||||
.btn-primary {
|
||||
@apply bg-blue-600 text-white px-4 py-2 rounded;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-green-600 text-white px-4 py-2 rounded;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
@apply bg-red-600 text-white px-4 py-2 rounded;
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
@apply bg-gray-400 text-white px-4 py-2 rounded;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
const { runningOrder, country, artist, title, flag, artistID } = defineProps(['runningOrder', 'country', 'artist', 'title', 'flag', 'artistID'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLink :to="`/review/${artistID}`">
|
||||
<div class="flex gap-4 border border-slate-200 justify-between overflow-clip items-center rounded-2xl">
|
||||
<h2 class="w-1/4 text-center">{{ runningOrder }}</h2>
|
||||
<div class="flex flex-col w-1/2">
|
||||
<h2>{{ country }}</h2>
|
||||
<p class="flex gap-2 text-sm">
|
||||
<span class="font-bold">{{ artist }}</span>
|
||||
<span class="italic">{{ title }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<img class="w-1/4" src="https://placehold.co/100" alt="{{ flag }}">
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<header class="p-4 shadow-md flex justify-between bg-slate-100">
|
||||
<h1><NuxtLink to="/">Eurovision 2025</NuxtLink></h1>
|
||||
<nav>
|
||||
<ul class="flex gap-4">
|
||||
<li><NuxtLink to="/profile">Profile</NuxtLink></li>
|
||||
<li><NuxtLink to="/login">Login</NuxtLink></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
const { category, id } = defineProps(['category', 'id'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="px-6">
|
||||
<h2>{{ category }}</h2>
|
||||
<input :id="`slider-${id}`" type="range" min="1" max="100" value="0" class="w-full"/>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.sliderSeparator {
|
||||
font-size: 0.8rem;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
+10
-2
@@ -1,5 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<title>Eurovision 2025</title>
|
||||
<Header />
|
||||
<div class="container mx-auto pt-6 p-4 bg-slate-400">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: #aaa;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<title>Kirjaudu</title>
|
||||
<div class="container mx-auto">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
+9
-1
@@ -1,5 +1,13 @@
|
||||
<script setup>
|
||||
const { data: participants } = await useFetch('/api/participants')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Index</h1>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div v-for="participant in participants" :key="participant.id">
|
||||
<ArtistListItem :runningOrder="participant.runningOrder" :country="participant.country" :artist="participant.artist" :title="participant.title" :flag="participant.flag" :artistID="participant.id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,3 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'login'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<template>
|
||||
<h1>Profile</h1>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
<script setup lang="ts">
|
||||
const { id } = useRoute().params
|
||||
|
||||
interface Artist {
|
||||
id: number
|
||||
year: number
|
||||
country: string
|
||||
artist: string
|
||||
title: string
|
||||
runningOrder: number
|
||||
lyricsOriginal: string
|
||||
lyricsTranslationFI: string
|
||||
tags: string[]
|
||||
img: string
|
||||
flag: string
|
||||
}
|
||||
|
||||
const { data: artist } = await useFetch<Artist>(`/api/artist?id=${id}`)
|
||||
|
||||
// State for toggling lyrics visibility
|
||||
const showOriginalLyrics = ref(false)
|
||||
const toggleOriginalLyrics = () => {
|
||||
showOriginalLyrics.value = !showOriginalLyrics.value
|
||||
}
|
||||
|
||||
const showTranslationLyrics = ref(false)
|
||||
const toggleTranslationLyrics = () => {
|
||||
showTranslationLyrics.value = !showTranslationLyrics.value
|
||||
}
|
||||
|
||||
const submitReview = () => {
|
||||
// Get slider values
|
||||
const songEl = document.getElementById('slider-song') as HTMLInputElement
|
||||
const showEl = document.getElementById('slider-show') as HTMLInputElement
|
||||
const costumeEl = document.getElementById('slider-costume') as HTMLInputElement
|
||||
|
||||
const songRating = songEl?.value || '0'
|
||||
const showRating = showEl?.value || '0'
|
||||
const costumeRating = costumeEl?.value || '0'
|
||||
|
||||
// Create review object
|
||||
const review = {
|
||||
artistId: id,
|
||||
ratings: {
|
||||
song: parseInt(songRating),
|
||||
show: parseInt(showRating),
|
||||
costume: parseInt(costumeRating)
|
||||
},
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
|
||||
console.log('Submitting review:', review)
|
||||
|
||||
// TODO: Send review to API
|
||||
// await useFetch('/api/reviews', {
|
||||
// method: 'POST',
|
||||
// body: review
|
||||
// })
|
||||
}
|
||||
</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.lyricsOriginal }}</pre>
|
||||
</div>
|
||||
<div v-if="artist.lyricsTranslationFI">
|
||||
<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.lyricsTranslationFI }}</pre>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="tag" v-for="tag in artist.tags" :key="tag">{{ tag }}</li>
|
||||
</ul>
|
||||
<form @submit.prevent="submitReview">
|
||||
<ReviewSlider id="song" category="Kappale"/>
|
||||
<ReviewSlider id="show" category="Lava show"/>
|
||||
<ReviewSlider id="costume" category="Asuste"/>
|
||||
<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;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,15 @@
|
||||
export default defineEventHandler((event) => {
|
||||
return {
|
||||
id: 1,
|
||||
year: 2025,
|
||||
country: "Suomi",
|
||||
artist: "Käärijä",
|
||||
title: "Cha Cha Cha",
|
||||
runningOrder: 1,
|
||||
lyricsOriginal: "[Säkeistö 1]\nRankka viikko ja paljon pitkii päiviä takan\nMielenkiintona piña colada ja rata\nIlta on vielä nuori ja aikaa kumota\nTää jäinen ulkokuori on aika tuhota\n\n[Kertosäe]\nPidän kaksin käsin kiinni juomista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, en mieti huomista ku tartun tuopista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, haluun olla sekasin ja vapaa huolista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, ja mä jatkan kunnes en enää pysy tuolissa niinku\n\n[Säkeistö 2]\nMuutama piña colada on jo takana\nSilti mul on vielä naamataulu vakava (Yeah, yeah, ye, ye, yeah)\nIlta on vielä nuori ja aikaa kumota\nTää jäinen ulkokuori on aika tuhota\nParketti kutsuu mua ku en oo enää lukossa\nNiinku cha-cha-cha, mä oon tulossa\n\n[Kertosäe]\nPidän kaksin käsin kiinni juomista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, en mieti huomista ku tartun tuopista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, haluun olla sekasin ja vapaa huolista niinku\n(Cha, cha, cha, cha, cha, cha, cha)\nEi, ja mä jatkan kunnes en enää pysy tuolissa niinku vou\nSee upcoming rock shows\nGet tickets for your favorite artists\nYou might also like\n\u200bmietin sua pahalla\n\u200bpehmoaino\nLet 3 - Mama ŠČ! (English Translation)\nGenius English Translations\nViimeinen tanssi\nBEHM & Olavi Uusivirta\n[Jälkikertosäe]\nNyt lähden tanssimaan\nNiinku cha-cha-cha\nEnkä pelkääkään tätä maailmaa\nNiinku cha-cha-cha\nKun mä kaadan päälleni samppanjaa\n\n[Väliosa]\n(Cha) Cha-cha-cha\nToinen silmä jo karsastaa\nJa puhe sammaltaa\nKu tää toinen puoli must vallan saa\n(Cha) Cha-cha-cha\nEn oo arkena tää mies laisinkaan\nEn oo mut tänään oon se mies\nTänään oon se mies (Ei)\n\n[Jälkikertosäe]\nNyt lähden tanssimaan\nNiinku cha-cha-cha\nEnkä pelkääkään tätä maailmaa\nNiinku cha-cha-cha\nKun mä kaadan päälleni samppanjaa\nNiinku cha-cha-cha\nCha, cha, cha, cha, cha, cha, cha, aa-aah\nNiinku cha-cha-cha\nCha, cha, cha, cha, cha, cha, cha\n[Outro]\nCha, cha, cha, cha, cha, cha, cha",
|
||||
lyricsTranslationFI: null,
|
||||
tags: ["Juhlat", "Alkoholi", "Sosiaalinen paine"],
|
||||
img: "https://placehold.co/150",
|
||||
flag: "fin"
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
export default defineEventHandler((event) => {
|
||||
return [
|
||||
{
|
||||
id: 1,
|
||||
year: 2025,
|
||||
country: "Suomi",
|
||||
artist: "Käärijä",
|
||||
title: "Cha Cha Cha",
|
||||
runningOrder: 1,
|
||||
lyricsOriginal: "Original lyrics",
|
||||
lyricsTranslationFI: "Käännös suomeksi",
|
||||
tags: [],
|
||||
img: "https://via.placeholder.com/150",
|
||||
flag: "fin"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
year: 2025,
|
||||
country: "Ruotsi",
|
||||
artist: "Loreen",
|
||||
title: "Loreen",
|
||||
runningOrder: 2,
|
||||
lyricsOriginal: "Original lyrics",
|
||||
lyricsTranslationFI: "Käännös suomeksi",
|
||||
tags: [],
|
||||
img: "https://via.placeholder.com/150",
|
||||
flag: "swe"
|
||||
},
|
||||
]
|
||||
})
|
||||
Reference in New Issue
Block a user