noita objectives + leaderboard

This commit is contained in:
2026-05-10 02:01:10 +02:00
parent 69b6b46ee2
commit 52a6a4adb2
4 changed files with 288 additions and 10 deletions
+81 -7
View File
@@ -8,9 +8,9 @@ interface Objective {
const userInfo = ref({
username: "Player",
rank: 42,
score: 15420,
runsSubmitted: 8,
rank: null as number | null,
score: 0,
runsSubmitted: 0,
});
const uploadedFiles = ref<File[]>([]);
@@ -18,6 +18,7 @@ const isUploading = ref(false);
const isDragover = ref(false);
const objectives = ref<Objective[]>([]);
const isLoadingObjectives = ref(false);
const isLoadingLeaderboard = ref(false);
const handleFileUpload = (event: Event) => {
const input = event.target as HTMLInputElement;
@@ -74,6 +75,13 @@ const submitRun = async () => {
uploadedFiles.value = [];
alert("Run submitted successfully!");
// Refresh objectives, score, and rank after successful submission
await Promise.all([
fetchObjectives(),
fetchUserResults(),
fetchLeaderboard(),
]);
} catch (error) {
console.error("Error submitting run:", error);
alert("Error submitting run. Please try again.");
@@ -100,8 +108,67 @@ const fetchObjectives = async () => {
}
};
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.runsSubmitted = results.objectives.length;
} catch (error) {
console.error("Error fetching results:", error);
}
};
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 leaderboard = await response.json();
// Find current user's rank
const userRank = leaderboard.leaderboard.find(
(entry: any) => entry.username === userInfo.value.username
);
if (userRank) {
userInfo.value.rank = userRank.rank;
userInfo.value.score = userRank.total_score;
}
} catch (error) {
console.error("Error fetching leaderboard:", error);
} finally {
isLoadingLeaderboard.value = false;
}
};
const loadUserData = async () => {
// Get user info first
try {
const response = await fetch("/api/user");
if (response.ok) {
const user = await response.json();
if (user.is_authenticated) {
userInfo.value.username = user.username;
}
}
} catch (error) {
console.error("Error fetching user info:", error);
}
// Fetch objectives, results, and leaderboard
await Promise.all([
fetchObjectives(),
fetchUserResults(),
fetchLeaderboard(),
]);
};
onMounted(() => {
fetchObjectives();
loadUserData();
});
</script>
@@ -139,10 +206,17 @@ onMounted(() => {
<div class="divider"></div>
<div class="space-y-4">
<div v-if="isLoadingLeaderboard" class="flex justify-center py-8">
<span class="loading loading-spinner loading-lg"></span>
</div>
<div v-else class="space-y-4">
<div class="text-center">
<p class="text-sm text-base-content/70 mb-1">Current Rank</p>
<p class="text-4xl font-bold text-primary">#{{ userInfo.rank }}</p>
<p v-if="userInfo.rank !== null" class="text-4xl font-bold text-primary">
#{{ userInfo.rank }}
</p>
<p v-else class="text-2xl text-base-content/50">No rank yet</p>
</div>
<div class="text-center">
@@ -151,7 +225,7 @@ onMounted(() => {
</div>
<div class="text-center">
<p class="text-sm text-base-content/70 mb-1">Runs Submitted</p>
<p class="text-sm text-base-content/70 mb-1">Objectives Completed</p>
<p class="text-2xl font-bold">{{ userInfo.runsSubmitted }}</p>
</div>
</div>