mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-06 03:20:13 +08:00
Merge branch 'main' into quest
This commit is contained in:
18 files changed
+315
-29
No files matched your search
@@ -1,12 +1,36 @@
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { ref } from 'vue'
|
||||
import { surveyUrl } from '../config'
|
||||
import { Vue3Lottie } from 'vue3-lottie'
|
||||
// import { surveyUrl } from '../config'
|
||||
import CompleteAnimation from '../img/complete-animation.json'
|
||||
|
||||
const showModal = ref(true) // Controls whether the modal is visible or not
|
||||
|
||||
const router = useRouter()
|
||||
const toast = useToast()
|
||||
const closeModal = () => {
|
||||
showModal.value = false
|
||||
}
|
||||
const defineComponent = () => ({
|
||||
components: {
|
||||
Vue3Lottie,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
CompleteAnimation,
|
||||
}
|
||||
},
|
||||
})
|
||||
const backtoMap = async () => {
|
||||
try {
|
||||
router.push({ name: 'map' })
|
||||
} catch (err) {
|
||||
// useToast().error('Failed to load map')
|
||||
toast.error('無法讀取地圖')
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate completing a quest to show the modal
|
||||
setTimeout(() => {
|
||||
@@ -18,6 +42,7 @@ setTimeout(() => {
|
||||
<div v-if="showModal" class="modal">
|
||||
<div class="modal-content bg-bg-secondary rounded-lg">
|
||||
<span class="close text-text" @click="closeModal">×</span>
|
||||
|
||||
<h2
|
||||
id="QuestCompleted"
|
||||
class="text-2xl text-text mb-5 w-full inline-flex justify-center"
|
||||
@@ -25,16 +50,34 @@ setTimeout(() => {
|
||||
<!-- Quest Completed! -->
|
||||
關卡完成!
|
||||
</h2>
|
||||
<p class="text-base text-text">
|
||||
<div class="z-10 right-1/2 top-1/2" @animationend="defineComponent">
|
||||
<Vue3Lottie
|
||||
:animationData="CompleteAnimation"
|
||||
:height="200"
|
||||
:width="200"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-base text-text text-center">恭喜你完成這一關!</p>
|
||||
<p class="text-base text-text text-center">
|
||||
接下來回到地圖,迎接新的挑戰吧!
|
||||
</p>
|
||||
<!-- <p class="text-base text-text">
|
||||
您已成功完成挑戰,真的非常感謝您的參與!<br />
|
||||
如果您能撥冗填寫這份問卷,我們將不勝感激,這對我們非常重要!
|
||||
</p>
|
||||
<a
|
||||
</p> -->
|
||||
<!-- <a
|
||||
id="SurveyButton"
|
||||
:href="surveyUrl"
|
||||
target="_blank"
|
||||
class="inline-flex justify-center rounded-lg text-base font-black py-2 mt-3 bg-text-primary w-full"
|
||||
>填寫問卷</a
|
||||
> -->
|
||||
<a
|
||||
id="BacktoMap"
|
||||
target="_blank"
|
||||
@click="backtoMap"
|
||||
class="inline-flex justify-center rounded-lg text-base font-black py-2 mt-3 bg-text-primary w-full"
|
||||
>回到地圖</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<script setup>
|
||||
import { defineProps, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { logout } from '../utils/auth'
|
||||
import { bugReportUrl } from '../config'
|
||||
import sessionStore, { reset } from '../store/session'
|
||||
import { reset } from '../store/session'
|
||||
import userProfileStore, {
|
||||
loadUserProfile,
|
||||
resetUserProfile,
|
||||
} from '../store/userProfile'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -12,6 +17,7 @@ const toast = useToast()
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await logout()
|
||||
resetUserProfile()
|
||||
reset()
|
||||
router.push({ name: 'login' })
|
||||
} catch (err) {
|
||||
@@ -29,6 +35,22 @@ const handleMap = async () => {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await loadUserProfile()
|
||||
} catch (err) {
|
||||
// toast.error('Failed to load user profile')
|
||||
toast.error('無法讀取使用者資料')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -47,13 +69,19 @@ const handleMap = async () => {
|
||||
class="text-border h-full w-full"
|
||||
/>
|
||||
</button> -->
|
||||
<p
|
||||
<button
|
||||
id="HeaderText"
|
||||
class="text-text-primary inline-block font-bold whitespace-nowrap"
|
||||
style="font-size: 2vh"
|
||||
v-if="sessionStore.quest"
|
||||
>
|
||||
{{ sessionStore.quest.title }}
|
||||
Linux Odyssey
|
||||
</button>
|
||||
<p
|
||||
id="HeaderText"
|
||||
class="text-text inline-block font-bold whitespace-nowrap"
|
||||
style="font-size: 2vh"
|
||||
>
|
||||
{{ title }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="h-full w-full flex gap-3 items-center justify-end">
|
||||
@@ -75,6 +103,13 @@ const handleMap = async () => {
|
||||
class="text-text-primary h-full w-full"
|
||||
/>
|
||||
</button> -->
|
||||
<p
|
||||
id="UsernameText"
|
||||
class="text-text inline-block whitespace-nowrap"
|
||||
style="font-size: 2vh"
|
||||
>
|
||||
{{ userProfileStore.username }}
|
||||
</p>
|
||||
<button title="Map" @click="handleMap" class="h-5 w-5">
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'map']"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable no-console -->
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
@@ -34,6 +35,7 @@ async function getQuests() {
|
||||
return res.data
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -93,9 +95,15 @@ const genOption = (nodes, edges) => ({
|
||||
itemStyle: {
|
||||
color: (params) => {
|
||||
const {
|
||||
data: { completed },
|
||||
data: { completed, unlocked },
|
||||
} = params
|
||||
return completed ? '#ADADB5' : '#454552'
|
||||
if (completed) {
|
||||
return '#00ff00'
|
||||
}
|
||||
if (unlocked) {
|
||||
return '#ADADB5'
|
||||
}
|
||||
return '454552'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user