refactor: improve review page with TypeScript interfaces and error handling
This commit is contained in:
+107
-66
@@ -9,44 +9,49 @@ interface Review {
|
|||||||
score_song: number
|
score_song: number
|
||||||
score_show: number
|
score_show: number
|
||||||
score_costume: number
|
score_costume: number
|
||||||
review_text: string
|
text_review?: string
|
||||||
created_at: string
|
created_at?: string
|
||||||
updated_at: string
|
updated_at?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Artist {
|
||||||
|
id: number
|
||||||
|
artist: string
|
||||||
|
title: string
|
||||||
|
img: string
|
||||||
|
lyrics_original: string
|
||||||
|
lyrics_translation_fi?: string
|
||||||
|
tags: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface User {
|
||||||
|
id: number
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config and route setup
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
const apiBase = config.public.apiBase
|
const apiBase = config.public.apiBase
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { id } = route.params
|
const { id } = route.params
|
||||||
|
|
||||||
// Initialize reactive data
|
// Reactive state
|
||||||
const artist = ref(null)
|
const artist = ref<Artist | null>(null)
|
||||||
const review = ref<Review>({})
|
const user = ref<User | null>(null)
|
||||||
const showOriginalLyrics = ref(false)
|
const review = ref<Review | null>(null)
|
||||||
const showTranslationLyrics = ref(false)
|
|
||||||
|
|
||||||
// Form data
|
// Form state with default values
|
||||||
const song = ref(50)
|
const song = ref(50)
|
||||||
const show = ref(50)
|
const show = ref(50)
|
||||||
const costume = ref(50)
|
const costume = ref(50)
|
||||||
const textReview = ref('')
|
const textReview = ref('')
|
||||||
|
const isSubmitting = ref(false)
|
||||||
|
|
||||||
// Get user from localStorage
|
// UI state
|
||||||
const user = ref(null)
|
const showOriginalLyrics = ref(false)
|
||||||
|
const showTranslationLyrics = ref(false)
|
||||||
|
|
||||||
// Initialize user data from localStorage on client side only
|
// Toggle functions for lyrics display
|
||||||
onMounted(() => {
|
|
||||||
if (process.client) {
|
|
||||||
const userData = localStorage.getItem('user')
|
|
||||||
if (userData) {
|
|
||||||
user.value = JSON.parse(userData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Functions to toggle lyrics visibility
|
|
||||||
function toggleOriginalLyrics() {
|
function toggleOriginalLyrics() {
|
||||||
showOriginalLyrics.value = !showOriginalLyrics.value
|
showOriginalLyrics.value = !showOriginalLyrics.value
|
||||||
}
|
}
|
||||||
@@ -55,63 +60,99 @@ function toggleTranslationLyrics() {
|
|||||||
showTranslationLyrics.value = !showTranslationLyrics.value
|
showTranslationLyrics.value = !showTranslationLyrics.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form submission function
|
// Load user data from localStorage
|
||||||
function submitReview() {
|
function loadUserData(): User | null {
|
||||||
const payload = {
|
if (!process.client) return null
|
||||||
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
|
const userData = localStorage.getItem('user')
|
||||||
console.log('Review submitted with data:', payload)
|
return userData ? JSON.parse(userData) : null
|
||||||
const response = fetch(`${apiBase}/reviews/`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch artist data based on ID
|
// Fetch artist data
|
||||||
onMounted(async () => {
|
async function fetchArtist() {
|
||||||
try {
|
try {
|
||||||
// Fetch song data
|
|
||||||
const response = await fetch(`${apiBase}/songs/${id}`)
|
const response = await fetch(`${apiBase}/songs/${id}`)
|
||||||
|
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`)
|
||||||
|
|
||||||
artist.value = await response.json()
|
artist.value = await response.json()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching artist data:', error)
|
console.error('Error fetching artist data:', error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get user from localStorage and then fetch reviews if user exists
|
// Fetch user's existing review for this song
|
||||||
if (process.client) {
|
async function fetchUserReview(userId: number) {
|
||||||
const userData = localStorage.getItem('user')
|
try {
|
||||||
if (userData) {
|
const response = await fetch(`${apiBase}/reviews/?song_id=${id}&user_id=${userId}`)
|
||||||
user.value = JSON.parse(userData)
|
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`)
|
||||||
|
|
||||||
// Now fetch reviews with the user ID
|
const reviewData = await response.json()
|
||||||
try {
|
review.value = reviewData
|
||||||
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
|
// Pre-fill form with existing review data
|
||||||
if (review.value) {
|
if (reviewData) {
|
||||||
song.value = review.value.score_song || 0
|
song.value = reviewData.score_song || 50
|
||||||
show.value = review.value.score_show || 0
|
show.value = reviewData.score_show || 50
|
||||||
costume.value = review.value.score_costume || 0
|
costume.value = reviewData.score_costume || 50
|
||||||
textReview.value = review.value.text_review || ''
|
textReview.value = reviewData.text_review || ''
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching review data:', error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching review data:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit review to the API
|
||||||
|
async function submitReview() {
|
||||||
|
if (!user.value?.id) {
|
||||||
|
console.error('User not authenticated')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isSubmitting.value = true
|
||||||
|
|
||||||
|
const payload: Review = {
|
||||||
|
song_id: Number(id),
|
||||||
|
user_id: user.value.id,
|
||||||
|
score_song: song.value,
|
||||||
|
score_show: show.value,
|
||||||
|
score_costume: costume.value,
|
||||||
|
text_review: textReview.value
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${apiBase}/reviews/`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`)
|
||||||
|
|
||||||
|
console.log('Review submitted successfully')
|
||||||
|
// You could add a success notification or redirect here
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error submitting review:', error)
|
||||||
|
// You could add an error notification here
|
||||||
|
} finally {
|
||||||
|
isSubmitting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize data on component mount
|
||||||
|
onMounted(async () => {
|
||||||
|
// Get user from localStorage
|
||||||
|
user.value = loadUserData()
|
||||||
|
|
||||||
|
// Fetch artist data
|
||||||
|
await fetchArtist()
|
||||||
|
|
||||||
|
// If user is logged in, fetch their review for this song
|
||||||
|
if (user.value?.id) {
|
||||||
|
await fetchUserReview(user.value.id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
Reference in New Issue
Block a user