use api in front
This commit is contained in:
+92
-40
@@ -2,14 +2,16 @@
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import PuzzleCard from './components/PuzzleCard.vue'
|
||||
import SubmissionForm from './components/SubmissionForm.vue'
|
||||
import { puzzleHelpers, submissionHelpers, errorHelpers } from './services/apiService'
|
||||
import type { SteamCollection, SteamCollectionItem, Submission, PuzzleResponse } from './types'
|
||||
|
||||
// Mock data - replace with actual API calls later
|
||||
// API data
|
||||
const collections = ref<SteamCollection[]>([])
|
||||
const puzzles = ref<SteamCollectionItem[]>([])
|
||||
const submissions = ref<Submission[]>([])
|
||||
const isLoading = ref(true)
|
||||
const showSubmissionModal = ref(false)
|
||||
const error = ref<string>('')
|
||||
|
||||
// Mock data for development
|
||||
const mockCollections: SteamCollection[] = [
|
||||
@@ -105,31 +107,83 @@ const responsesByPuzzle = computed(() => {
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
// Simulate API loading
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
|
||||
collections.value = mockCollections
|
||||
puzzles.value = mockPuzzles
|
||||
isLoading.value = false
|
||||
try {
|
||||
isLoading.value = true
|
||||
error.value = ''
|
||||
|
||||
// Load puzzles from API
|
||||
const loadedPuzzles = await puzzleHelpers.loadPuzzles()
|
||||
puzzles.value = loadedPuzzles
|
||||
|
||||
// Create mock collection from loaded puzzles for display
|
||||
if (loadedPuzzles.length > 0) {
|
||||
collections.value = [{
|
||||
id: 1,
|
||||
steam_id: '3479142989',
|
||||
title: 'PolyLAN 41',
|
||||
description: 'Puzzle collection for PolyLAN 41 fil rouge',
|
||||
author_name: 'Flame Legrems',
|
||||
total_items: loadedPuzzles.length,
|
||||
unique_visitors: 31,
|
||||
current_favorites: 1,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
}]
|
||||
}
|
||||
|
||||
// Load existing submissions
|
||||
const loadedSubmissions = await submissionHelpers.loadSubmissions()
|
||||
submissions.value = loadedSubmissions
|
||||
|
||||
} catch (err) {
|
||||
error.value = errorHelpers.getErrorMessage(err)
|
||||
console.error('Failed to load data:', err)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
const handleSubmission = (submission: Submission) => {
|
||||
console.log('Submission received:', submission)
|
||||
|
||||
// Add submission to the list
|
||||
submissions.value.push({
|
||||
...submission,
|
||||
id: Date.now(), // Simple ID generation for demo
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
|
||||
// Show success message
|
||||
const puzzleNames = submission.responses.map(r => r.puzzle_name).join(', ')
|
||||
alert(`Solutions submitted for puzzles: ${puzzleNames}`)
|
||||
|
||||
// Close modal
|
||||
showSubmissionModal.value = false
|
||||
const handleSubmission = async (submissionData: {
|
||||
files: any[],
|
||||
notes?: string
|
||||
}) => {
|
||||
try {
|
||||
isLoading.value = true
|
||||
error.value = ''
|
||||
|
||||
// Create submission via API
|
||||
const response = await submissionHelpers.createFromFiles(
|
||||
submissionData.files,
|
||||
puzzles.value,
|
||||
submissionData.notes
|
||||
)
|
||||
|
||||
if (response.error) {
|
||||
error.value = response.error
|
||||
alert(`Submission failed: ${response.error}`)
|
||||
return
|
||||
}
|
||||
|
||||
if (response.data) {
|
||||
// Add to local submissions list
|
||||
submissions.value.unshift(response.data)
|
||||
|
||||
// Show success message
|
||||
const puzzleNames = response.data.responses.map(r => r.puzzle_name).join(', ')
|
||||
alert(`Solutions submitted successfully for puzzles: ${puzzleNames}`)
|
||||
|
||||
// Close modal
|
||||
showSubmissionModal.value = false
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
const errorMessage = errorHelpers.getErrorMessage(err)
|
||||
error.value = errorMessage
|
||||
alert(`Submission failed: ${errorMessage}`)
|
||||
console.error('Submission error:', err)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const openSubmissionModal = () => {
|
||||
@@ -142,22 +196,7 @@ const closeSubmissionModal = () => {
|
||||
|
||||
// Function to match puzzle name from OCR to actual puzzle
|
||||
const findPuzzleByName = (ocrPuzzleName: string): SteamCollectionItem | null => {
|
||||
if (!ocrPuzzleName) return null
|
||||
|
||||
// Try exact match first
|
||||
let match = puzzles.value.find(p =>
|
||||
p.title.toLowerCase() === ocrPuzzleName.toLowerCase()
|
||||
)
|
||||
|
||||
if (!match) {
|
||||
// Try partial match
|
||||
match = puzzles.value.find(p =>
|
||||
p.title.toLowerCase().includes(ocrPuzzleName.toLowerCase()) ||
|
||||
ocrPuzzleName.toLowerCase().includes(p.title.toLowerCase())
|
||||
)
|
||||
}
|
||||
|
||||
return match || null
|
||||
return puzzleHelpers.findPuzzleByName(puzzles.value, ocrPuzzleName)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -181,6 +220,19 @@ const findPuzzleByName = (ocrPuzzleName: string): SteamCollectionItem | null =>
|
||||
<p class="mt-4 text-base-content/70">Loading puzzles...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error State -->
|
||||
<div v-else-if="error" class="alert alert-error max-w-2xl mx-auto">
|
||||
<i class="mdi mdi-alert-circle text-xl"></i>
|
||||
<div>
|
||||
<h3 class="font-bold">Error Loading Data</h3>
|
||||
<div class="text-sm">{{ error }}</div>
|
||||
</div>
|
||||
<button @click="window.location.reload()" class="btn btn-sm btn-outline">
|
||||
<i class="mdi mdi-refresh mr-1"></i>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div v-else class="space-y-8">
|
||||
|
||||
Reference in New Issue
Block a user