185 lines
4.7 KiB
TypeScript
185 lines
4.7 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
|
|
export interface Objective {
|
|
objectiv_id: string
|
|
display_string: string
|
|
first_seen_at: string | null
|
|
count: number
|
|
max_count: number
|
|
seed: string | null
|
|
points_per_objectiv: number
|
|
total_points: number
|
|
}
|
|
|
|
interface UserInfo {
|
|
username: string
|
|
rank: number | null
|
|
score: number
|
|
runsSubmitted: number
|
|
deathsCount: number
|
|
isStaff: boolean
|
|
}
|
|
|
|
interface LeaderboardEntry {
|
|
rank: number
|
|
username: string
|
|
total_score: number
|
|
objectives_count: number
|
|
deaths_count: number
|
|
is_staff: boolean
|
|
}
|
|
|
|
export const useNoitaStore = defineStore('noita', () => {
|
|
// State
|
|
const userInfo = ref<UserInfo>({
|
|
username: 'Player',
|
|
rank: null,
|
|
score: 0,
|
|
runsSubmitted: 0,
|
|
deathsCount: 0,
|
|
isStaff: false,
|
|
})
|
|
const objectives = ref<Objective[]>([])
|
|
const leaderboard = ref<LeaderboardEntry[]>([])
|
|
const isLoadingLeaderboard = ref(false)
|
|
const isUploading = ref(false)
|
|
const error = ref<string>('')
|
|
|
|
// Actions
|
|
const fetchUserResults = async () => {
|
|
try {
|
|
const response = await fetch('/api/noita/results')
|
|
if (!response.ok) throw new Error('Failed to fetch results')
|
|
|
|
const results = await response.json()
|
|
userInfo.value.score = results.total_score
|
|
userInfo.value.deathsCount = results.deaths_count
|
|
userInfo.value.runsSubmitted = results.objectives.length
|
|
objectives.value = results.objectives
|
|
} catch (err) {
|
|
error.value = 'Failed to fetch user results'
|
|
console.error('Error fetching results:', err)
|
|
}
|
|
}
|
|
|
|
const fetchLeaderboard = async () => {
|
|
isLoadingLeaderboard.value = true
|
|
try {
|
|
const response = await fetch('/api/noita/leaderboard')
|
|
if (!response.ok) throw new Error('Failed to fetch leaderboard')
|
|
|
|
const data = await response.json()
|
|
leaderboard.value = data.leaderboard
|
|
|
|
// Find current user's rank
|
|
const userRank = leaderboard.value.find(
|
|
(entry) => entry.username === userInfo.value.username
|
|
)
|
|
|
|
if (userRank) {
|
|
userInfo.value.rank = userRank.rank
|
|
userInfo.value.score = userRank.total_score
|
|
userInfo.value.deathsCount = userRank.deaths_count
|
|
}
|
|
} catch (err) {
|
|
error.value = 'Failed to fetch leaderboard'
|
|
console.error('Error fetching leaderboard:', err)
|
|
} finally {
|
|
isLoadingLeaderboard.value = false
|
|
}
|
|
}
|
|
|
|
const loadUserData = async () => {
|
|
try {
|
|
const response = await fetch('/api/user')
|
|
if (response.ok) {
|
|
const user = await response.json()
|
|
if (user.is_authenticated) {
|
|
userInfo.value.username = user.username
|
|
userInfo.value.isStaff = user.is_staff || false
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching user info:', err)
|
|
}
|
|
|
|
await Promise.all([fetchUserResults(), fetchLeaderboard()])
|
|
}
|
|
|
|
const submitRun = async (files: File[]) => {
|
|
if (files.length === 0) return
|
|
|
|
isUploading.value = true
|
|
try {
|
|
for (const file of files) {
|
|
const formData = new FormData()
|
|
formData.append('file', file)
|
|
|
|
const response = await fetch('/api/noita/submit', {
|
|
method: 'POST',
|
|
body: formData,
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json()
|
|
throw new Error(errorData.detail || 'Unknown error')
|
|
}
|
|
|
|
const result = await response.json()
|
|
console.log('Submission successful:', result)
|
|
}
|
|
|
|
// Refresh objectives, score, and rank after successful submission
|
|
await Promise.all([fetchUserResults(), fetchLeaderboard()])
|
|
} catch (err) {
|
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error'
|
|
error.value = `Error submitting run: ${errorMessage}`
|
|
throw err
|
|
} finally {
|
|
isUploading.value = false
|
|
}
|
|
}
|
|
|
|
const clearCache = async () => {
|
|
try {
|
|
const response = await fetch('/api/cache/clear', {
|
|
method: 'POST',
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json()
|
|
throw new Error(errorData.detail || 'Unknown error')
|
|
}
|
|
|
|
await Promise.all([fetchUserResults(), fetchLeaderboard()])
|
|
} catch (err) {
|
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error'
|
|
error.value = `Error clearing cache: ${errorMessage}`
|
|
throw err
|
|
}
|
|
}
|
|
|
|
const refreshData = async () => {
|
|
await Promise.all([fetchUserResults(), fetchLeaderboard()])
|
|
}
|
|
|
|
return {
|
|
// State
|
|
userInfo,
|
|
objectives,
|
|
leaderboard,
|
|
isLoadingLeaderboard,
|
|
isUploading,
|
|
error,
|
|
|
|
// Actions
|
|
fetchUserResults,
|
|
fetchLeaderboard,
|
|
loadUserData,
|
|
submitRun,
|
|
clearCache,
|
|
refreshData,
|
|
}
|
|
})
|