import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const useQuizStore = defineStore('quiz', () => { // State const userPoints = ref(0) const currentStreak = ref(0) const lastPlayedDate = ref(null) const questions = ref([]) const isLoading = ref(false) const error = ref(null) // Getters const canPlayToday = computed(() => { if (!lastPlayedDate.value) return true const last = new Date(lastPlayedDate.value) const now = new Date() // Reset at midnight (different calendar day) const lastDay = last.toDateString() const today = now.toDateString() return lastDay !== today }) const totalQuestions = computed(() => questions.value.length) // Helper function to get auth token function getAuthToken() { if (typeof window !== 'undefined') { // Try both token keys for compatibility return localStorage.getItem('token') || localStorage.getItem('auth_token') } return null } // Helper function for API calls async function apiFetch(url, options = {}) { const token = getAuthToken() const headers = { 'Content-Type': 'application/json', ...options.headers } if (token) { headers['Authorization'] = `Bearer ${token}` } const response = await fetch(`${import.meta.env.VITE_API_BASE_URL || 'https://dev.servicefinder.hu'}${url}`, { ...options, headers }) if (!response.ok) { const errorText = await response.text() throw new Error(`API error ${response.status}: ${errorText}`) } return response.json() } // Actions async function fetchQuizStats() { isLoading.value = true error.value = null try { const data = await apiFetch('/api/v1/gamification/quiz/stats') userPoints.value = data.total_quiz_points || 0 currentStreak.value = data.current_streak || 0 lastPlayedDate.value = data.last_played || null return data } catch (err) { console.error('Failed to fetch quiz stats:', err) error.value = err.message // Fallback to localStorage if API fails userPoints.value = getStoredPoints() currentStreak.value = getStoredStreak() lastPlayedDate.value = getStoredLastPlayedDate() return { total_quiz_points: userPoints.value, current_streak: currentStreak.value, last_played: lastPlayedDate.value, can_play_today: canPlayToday.value } } finally { isLoading.value = false } } async function fetchDailyQuiz() { isLoading.value = true error.value = null try { const data = await apiFetch('/api/v1/gamification/quiz/daily') questions.value = data.questions || [] return data } catch (err) { console.error('Failed to fetch daily quiz:', err) error.value = err.message // Fallback to mock questions if API fails questions.value = getMockQuestions() return { questions: questions.value, total_questions: questions.value.length, date: new Date().toISOString().split('T')[0] } } finally { isLoading.value = false } } async function answerQuestion(questionId, selectedOptionIndex) { try { const response = await apiFetch('/api/v1/gamification/quiz/answer', { method: 'POST', body: JSON.stringify({ question_id: questionId, selected_option: selectedOptionIndex }) }) if (response.is_correct) { userPoints.value += response.points_awarded currentStreak.value += 1 persistState() // Update localStorage as fallback } else { currentStreak.value = 0 } return response } catch (err) { console.error('Failed to submit quiz answer:', err) error.value = err.message // Fallback to local logic return answerQuestionLocal(questionId, selectedOptionIndex) } } async function completeDailyQuiz() { try { await apiFetch('/api/v1/gamification/quiz/complete', { method: 'POST' }) lastPlayedDate.value = new Date().toISOString() persistState() } catch (err) { console.error('Failed to complete daily quiz:', err) error.value = err.message // Fallback to local storage lastPlayedDate.value = new Date().toISOString() persistState() } } // Local fallback functions function answerQuestionLocal(questionId, selectedOptionIndex) { const question = questions.value.find(q => q.id === questionId) if (!question) return { is_correct: false, correct_answer: -1, explanation: 'Question not found' } const isCorrect = selectedOptionIndex === question.correctAnswer if (isCorrect) { userPoints.value += 10 currentStreak.value += 1 } else { currentStreak.value = 0 } persistState() return { is_correct: isCorrect, correct_answer: question.correctAnswer, points_awarded: isCorrect ? 10 : 0, explanation: question.explanation } } function resetStreak() { currentStreak.value = 0 persistState() } function addPoints(points) { userPoints.value += points persistState() } // SSR-safe localStorage persistence (fallback only) function persistState() { if (typeof window !== 'undefined') { localStorage.setItem('quiz_points', userPoints.value.toString()) localStorage.setItem('quiz_streak', currentStreak.value.toString()) localStorage.setItem('quiz_last_played', lastPlayedDate.value) } } function getStoredPoints() { if (typeof window !== 'undefined') { return parseInt(localStorage.getItem('quiz_points') || '0') } return 0 } function getStoredStreak() { if (typeof window !== 'undefined') { return parseInt(localStorage.getItem('quiz_streak') || '0') } return 0 } function getStoredLastPlayedDate() { if (typeof window !== 'undefined') { return localStorage.getItem('quiz_last_played') || null } return null } function getMockQuestions() { return [ { id: 1, question: 'Melyik alkatrész felelős a motor levegő‑üzemanyag keverékének szabályozásáért?', options: ['Generátor', 'Lambda‑szonda', 'Féktárcsa', 'Olajszűrő'], correctAnswer: 1, explanation: 'A lambda‑szonda méri a kipufogógáz oxigéntartalmát, és ezen alapul a befecskendezés.' }, { id: 2, question: 'Mennyi ideig érvényes egy gépjármű műszaki vizsgája Magyarországon?', options: ['1 év', '2 év', '4 év', '6 év'], correctAnswer: 1, explanation: 'A személygépkocsik műszaki vizsgája 2 évre érvényes, kivéve az újonnan forgalomba helyezett autókat.' }, { id: 3, question: 'Melyik anyag NEM része a hibrid autók akkumulátorának?', options: ['Lítium', 'Nikkel', 'Ólom', 'Kobalt'], correctAnswer: 2, explanation: 'A hibrid és elektromos autók akkumulátoraiban általában lítium, nikkel és kobalt található, ólom az ólom‑savas akkukban van.' } ] } // Initialize store with stats - DISABLED for debugging // fetchQuizStats() console.log('🚨 Quiz store: Auto-fetch DISABLED for debugging') return { userPoints, currentStreak, lastPlayedDate, questions, canPlayToday, totalQuestions, isLoading, error, fetchQuizStats, fetchDailyQuiz, answerQuestion, completeDailyQuiz, resetStreak, addPoints } })