519 lines
21 KiB
Vue
519 lines
21 KiB
Vue
<template>
|
|
<div class="min-h-screen flex flex-col items-center justify-center bg-gradient-to-b
|
|
from-green-100 to-green-300 pb-28 pr-2 pl-2 mb-[-10px]"
|
|
style="background-image:url('/images/footer.png');
|
|
background-repeat:no-repeat;
|
|
background-position:bottom;
|
|
background-size: 100% 200px;"
|
|
margin-bottom=-10px;
|
|
>
|
|
<!-- Character Preview -->
|
|
<div class="w-full max-w-md flex flex-col items-center z-60 mb-8">
|
|
<div class="relative flex items-end justify-center z-30 px-[10px] mt-[40px]">
|
|
<img
|
|
src="/images/logo.png"
|
|
:alt="selectedCharacter.name"
|
|
class="object-contain relative z-30 pb-0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="w-full max-w-md flex flex-col items-center z-60">
|
|
<div class="bg-lime-200 shadow-xl rounded-2xl p-6 flex flex-col items-center
|
|
relative w-full px-[10px] mx-[10px] bg-cover bg-center bg-no-repeat"
|
|
style="background-image: url('/images/bghero.jpg')">
|
|
<div class="relative w-40 h-50 flex items-end justify-center z-30 px-[10px] mt-[40px]">
|
|
<img
|
|
:src="selectedCharacter.img"
|
|
:alt="selectedCharacter.name"
|
|
class="w-40 h-60 object-contain relative z-30 pb-12"
|
|
/>
|
|
</div>
|
|
<div class="flex flex-row items-start justify-between gap-12 w-full pt-5 absolute bottom-2 left-2 pr-5">
|
|
<div class="bg-white w-[90px] h-[60px] rounded-xl p-1 shadow-lg flex flex-col bottom-0">
|
|
<span class="text-xs font-bold text-gray-800 items-center text-center">{{ 'KOIN' }}</span>
|
|
<div class="flex items-end justify-center gap-2 p-1">
|
|
<img src="/images/token-poin.svg" alt="coin" class="w-6 h-6" />
|
|
<span>100</span>
|
|
</div>
|
|
</div>
|
|
<div class="bg-white w-[90px] h-[60px] rounded-xl p-1 shadow-lg flex flex-col bottom-0">
|
|
<span class="text-xs font-bold text-gray-800 items-center text-center">{{ 'Dayly Quest' }}</span>
|
|
<div class="flex items-end justify-center gap-2 p-1">
|
|
<span>3/10</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center justify-center w-[30px] h-[30px] rounded-full border-4 border-green-500 hover:bg-green-400 absolute top-2 right-2">
|
|
<img src="/images/but-nav-koleksi.png" alt="img" class="w-[20px] h-[20px] "
|
|
@click="changeAva('character')">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="logo w-full max-w-md flex flex-col items-center mt-4">
|
|
<div class="bg-grey shadow-xl rounded-2xl px-16 py-1 flex flex-col items-center">
|
|
<h2 class="mt-4 mb-4 text-md font-bold text-grey-400">Level 10 - Hari ke-2</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Character Selection -->
|
|
<!-- <div class="w-full max-w-md flex flex-col items-center bg-green-grey py-[0px] mx-[10px] md:mx-0
|
|
transform transition-transform duration-300 hover:scale-105
|
|
">
|
|
<div class="rounded-3xl p-6 shadow-2xl-soft flex items-start gap-4 w-full py-[10px] my-[20px]"
|
|
:class="isDone ? ' bg-lime-500' : 'bg-white'" >
|
|
<div class="flex-shrink-0 mt-1">
|
|
<img src="/images/qicon1.png" alt="Quest Icon" class="w-12 h-12" />
|
|
</div>
|
|
|
|
<div class="flex-1">
|
|
<h2 class="text-xl font-bold text-gray-800">{{ 'BANGUN PAGI' }}</h2>
|
|
<p class="text-sm text-gray-600 mb-2">{{ 'Mulai hari dengan semangat.!' }}</p>
|
|
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-gray-500" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a8 8 0 100 16 8 8 0 000-16zM9 11V5a1 1 0 012 0v6a1 1 0 01-2 0zM10 13a1 1 0 100 2 1 1 0 000-2z"/></svg>
|
|
{{ '12:20' }}
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20"><path d="M10 15a5 5 0 100-10 5 5 0 000 10z"/><path fill-rule="evenodd" d="M10 0a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 100-16 8 8 0 000 16z" clip-rule="evenodd"/></svg>
|
|
+{{ '1000' }} koin
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-green-600 transform rotate-180" fill="currentColor" viewBox="0 0 20 20"><path d="M10 14a1 1 0 01-.707-.293l-4-4a1 1 0 011.414-1.414L10 11.586l3.293-3.293a1 1 0 011.414 1.414l-4 4A1 1 0 0110 14z"/></svg>
|
|
+{{ '100' }}mm
|
|
</span>
|
|
</div>
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<button class="w-full mt-4 py-2 px-4 rounded-lg bg-green-600 text-white font-bold hover:bg-green-700 transition">MULAI QUEST</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
<div
|
|
v-for="mission in missions"
|
|
:key="mission.id"
|
|
|
|
class="w-full max-w-md flex flex-col items-center bg-white-grey py-[0px] mx-2.5 md:mx-5
|
|
transform transition-transform duration-300 hover:scale-105"
|
|
>
|
|
<!-- <div class="bg-white rounded-3xl p-6 shadow-2xl-soft flex items-start gap-4 w-full py-[10px] my-[20px]">
|
|
<div class="flex-shrink-0 mt-1">
|
|
<img src="/images/qicon2.png" alt="Quest Icon" class="w-12 h-12" />
|
|
</div>
|
|
<div class="flex-1">
|
|
<h2 class="text-xl font-bold text-gray-800">{{ mission.name }}</h2>
|
|
<p class="text-sm text-gray-600 mb-2">{{ mission.description }}</p>
|
|
<p class="text-xs font-semibold"
|
|
:class="{
|
|
'text-green-600': mission.userStatus === 'completed',
|
|
'text-yellow-600': mission.userStatus === 'in_progress',
|
|
'text-gray-500': mission.userStatus === 'not_started'
|
|
}">
|
|
Status: {{ mission.userStatus }}
|
|
</p>
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M10 2a8 8 0 100 16 8 8 0 000-16zM9 11V5a1 1 0 012 0v6a1 1 0 01-2 0zM10 13a1 1 0 100 2 1 1 0 000-2z"/>
|
|
</svg>
|
|
{{ timeLeft(mission.date_valid, mission.time_to_valid) }}
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20"><path d="M10 15a5 5 0 100-10 5 5 0 000 10z"/><path fill-rule="evenodd" d="M10 0a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 100-16 8 8 0 000 16z" clip-rule="evenodd"/></svg>
|
|
+{{ mission.coin }} koin
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-green-600 transform rotate-180" fill="currentColor" viewBox="0 0 20 20"><path d="M10 14a1 1 0 01-.707-.293l-4-4a1 1 0 011.414-1.414L10 11.586l3.293-3.293a1 1 0 011.414 1.414l-4 4A1 1 0 0110 14z"/></svg>
|
|
+{{ '100' }}mm
|
|
</span>
|
|
</div>
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<button v-if="!mission.userStatus ==='completed'" class="w-full mt-4 py-2 px-4 rounded-lg bg-red-600 text-white font-bold
|
|
hover:bg-green-700 transition"
|
|
@click="handleMissionClick(mission)"
|
|
>
|
|
{{ mission.userStatus === 'completed' ? 'SELESAI' :
|
|
mission.userStatus === 'in_progress' ? 'LANJUTKAN' :
|
|
'MULAI QUEST' }}
|
|
</button>
|
|
<span v-else >Selesai</span>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
|
|
<div
|
|
class="relative rounded-3xl p-6 shadow-2xl-soft flex items-start gap-4 w-full py-[10px] my-[20px] overflow-hidden"
|
|
:class="{
|
|
'bg-green-100 pointer-events-none opacity-95': mission.userStatus === 'completed',
|
|
'bg-yellow-100': mission.userStatus === 'in_progress',
|
|
'bg-white hover:scale-105': mission.userStatus === 'not_started'
|
|
}"
|
|
>
|
|
<!-- ✅ Stamp layer BEHIND content -->
|
|
<div
|
|
v-if="mission.userStatus === 'completed'"
|
|
class="absolute inset-0 flex justify-end items-center pr-6 z-0"
|
|
>
|
|
<span
|
|
class="text-[64px] font-extrabold text-green-600/15 rotate-[-20deg] select-none pointer-events-none"
|
|
style="mix-blend-mode: multiply;"
|
|
>
|
|
SELESAI
|
|
</span>
|
|
</div>
|
|
|
|
<!-- ✅ Content layer ABOVE stamp -->
|
|
<div class="flex-shrink-0 mt-1 relative z-10">
|
|
<img src="/images/qicon2.png" alt="Quest Icon" class="w-12 h-12" />
|
|
</div>
|
|
|
|
<div class="flex-1 relative z-10">
|
|
<h2 class="text-xl font-bold text-gray-800">{{ mission.name }}</h2>
|
|
<p class="text-sm text-gray-600 mb-2">{{ mission.description }}</p>
|
|
|
|
<p
|
|
class="text-xs font-semibold"
|
|
:class="{
|
|
'text-green-600': mission.userStatus === 'completed',
|
|
'text-yellow-600': mission.userStatus === 'in_progress',
|
|
'text-gray-500': mission.userStatus === 'not_started'
|
|
}"
|
|
>
|
|
Status: {{ mission.userStatus }}
|
|
</p>
|
|
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
|
|
<path
|
|
d="M10 2a8 8 0 100 16 8 8 0 000-16zM9 11V5a1 1 0 012 0v6a1 1 0 01-2 0zM10 13a1 1 0 100 2 1 1 0 000-2z"
|
|
/>
|
|
</svg>
|
|
{{ timeLeft(mission.date_valid, mission.time_to_valid) }}
|
|
</span>
|
|
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20">
|
|
<path d="M10 15a5 5 0 100-10 5 5 0 000 10z" />
|
|
<path
|
|
fill-rule="evenodd"
|
|
d="M10 0a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 100-16 8 8 0 000 16z"
|
|
clip-rule="evenodd"
|
|
/>
|
|
</svg>
|
|
+{{ mission.coin }} koin
|
|
</span>
|
|
|
|
<span class="flex items-center gap-1">
|
|
<svg
|
|
class="w-4 h-4 text-green-600 transform rotate-180"
|
|
fill="currentColor"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path
|
|
d="M10 14a1 1 0 01-.707-.293l-4-4a1 1 0 011.414-1.414L10 11.586l3.293-3.293a1 1 0 011.414 1.414l-4 4A1 1 0 0110 14z"
|
|
/>
|
|
</svg>
|
|
+100mm
|
|
</span>
|
|
</div>
|
|
|
|
<!-- ✅ Button or empty block -->
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<button
|
|
v-if="mission.userStatus !== 'completed'"
|
|
class="w-full mt-4 py-2 px-4 rounded-lg bg-red-600 text-white font-bold hover:bg-green-700 transition"
|
|
@click="handleMissionClick(mission)"
|
|
>
|
|
{{ mission.userStatus === 'in_progress' ? 'LANJUTKAN' : 'MULAI QUEST' }}
|
|
</button>
|
|
<div v-else class="w-full mt-4 py-4 px-4"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<!-- <div class="w-full max-w-md flex flex-col items-center bg-green-grey py-[0px] mx-2.5 md:mx-5
|
|
transform transition-transform duration-300 hover:scale-105
|
|
">
|
|
<div class="bg-white rounded-3xl p-6 shadow-2xl-soft flex items-start gap-4 w-full py-[10px] my-[20px]">
|
|
<div class="flex-shrink-0 mt-1">
|
|
<img src="/images/qicon3.png" alt="Quest Icon" class="w-12 h-12" />
|
|
</div>
|
|
|
|
<div class="flex-1">
|
|
<h2 class="text-xl font-bold text-gray-800">{{ 'CERITA HARI INI' }}</h2>
|
|
<p class="text-sm text-gray-600 mb-2">{{ 'Berbagi cerita seru hari ini' }}</p>
|
|
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-gray-500" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a8 8 0 100 16 8 8 0 000-16zM9 11V5a1 1 0 012 0v6a1 1 0 01-2 0zM10 13a1 1 0 100 2 1 1 0 000-2z"/></svg>
|
|
{{ '12:20' }}
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20"><path d="M10 15a5 5 0 100-10 5 5 0 000 10z"/><path fill-rule="evenodd" d="M10 0a10 10 0 100 20 10 10 0 000-20zm0 18a8 8 0 100-16 8 8 0 000 16z" clip-rule="evenodd"/></svg>
|
|
+{{ '1000' }} koin
|
|
</span>
|
|
<span class="flex items-center gap-1">
|
|
<svg class="w-4 h-4 text-red-600 transform rotate-180" fill="currentColor" viewBox="0 0 20 20"><path d="M10 14a1 1 0 01-.707-.293l-4-4a1 1 0 011.414-1.414L10 11.586l3.293-3.293a1 1 0 011.414 1.414l-4 4A1 1 0 0110 14z"/></svg>
|
|
+{{ '100' }}mm
|
|
</span>
|
|
</div>
|
|
<div class="flex items-center gap-4 text-xs text-gray-700">
|
|
<button class="w-full mt-4 py-2 px-4 rounded-lg bg-red-600 text-white font-bold hover:bg-green-700 transition">MULAI QUEST</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
<!-- Modal -->
|
|
<div
|
|
v-if="showModal"
|
|
class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
|
|
>
|
|
<div class="bg-white rounded-lg p-6 w-80 max-h-[80vh] overflow-auto relative">
|
|
<h2 class="text-xl font-bold mb-4">Pilih {{ modalType === 'profile' ? 'Profil' : 'Karakter' }}</h2>
|
|
|
|
<!-- Tombol close -->
|
|
<button
|
|
@click="showModal = false"
|
|
class="absolute top-2 right-2 text-gray-500 hover:text-gray-800"
|
|
>
|
|
✕
|
|
</button>
|
|
|
|
<!-- List karakter -->
|
|
<div class="grid grid-cols-3 gap-4" v-if="modalType === 'profile'">
|
|
<div
|
|
v-for="prof in profiles"
|
|
:key="prof.name"
|
|
@click="profileListSelected(prof)"
|
|
class="cursor-pointer hover:scale-105 transform transition flex flex-col items-center"
|
|
>
|
|
<img :src="prof.img" :alt="prof.name" class="w-16 h-16 rounded"/>
|
|
<span class="text-sm mt-1">{{ prof.name }}</span>
|
|
</div>
|
|
<!-- Full-width logout area -->
|
|
<div class="col-span-3 flex justify-center mt-6">
|
|
<button
|
|
@click="handleLogout"
|
|
class="flex items-center gap-2 bg-gradient-to-r from-red-500 to-rose-600
|
|
hover:from-red-600 hover:to-rose-700 text-white font-semibold py-2 px-6
|
|
rounded-full shadow-md hover:shadow-lg transform transition-all duration-200
|
|
hover:scale-105 active:scale-95 focus:outline-none focus:ring-2 focus:ring-red-400"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none"
|
|
viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h6a2 2 0 012 2v1" />
|
|
</svg>
|
|
<span>Logout</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-3 gap-4" v-if="modalType === 'character'">
|
|
<div
|
|
v-for="char in characters"
|
|
:key="char.name"
|
|
@click="clickCharacter(char)"
|
|
class="cursor-pointer hover:scale-105 transform transition flex flex-col items-center"
|
|
>
|
|
<img :src="char.img" :alt="char.name" class="w-16 h-16 rounded"/>
|
|
<span class="text-sm mt-1">{{ char.name }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getContent } from '@/services/content';
|
|
import { getMissions,getMissionLogs, createMissionLog } from '@/services/missions';
|
|
export default {
|
|
name: "App",
|
|
data() {
|
|
return {
|
|
characters: [
|
|
{ name: "Bear", img: "../images/char/bear.png" },
|
|
{ name: "Rabbit", img: "../images/char/rabbit.png" },
|
|
{ name: "Fox", img: "../images/char/fox.png" },
|
|
{ name: "Brown Bear", img: "../images/char/brownbear.png" },
|
|
{ name: "Lion", img: "../images/char/lion.png" },
|
|
{ name: "Monkey", img: "../images/char/monkey.png" },
|
|
{ name: "Pig", img: "../images/char/pig.png" },
|
|
{ name: "Sheep", img: "../images/char/sheep.png" },
|
|
{ name: "Tiger", img: "../images/char/tiger.png" },
|
|
],
|
|
|
|
profiles : [
|
|
{name : "profile", img: "/images/propic-001.svg"},
|
|
{name : "profile", img: "/images/propic-blank.svg"},
|
|
],
|
|
|
|
selectedCharacter: { name: "Tiger", img: "../images/char/tiger.png" },
|
|
showModal:false,
|
|
selectedProfile : {name : "profile", img: "/images/propic-001.svg"},
|
|
modalType : "profile",
|
|
isDone : true,
|
|
contents : getContent(),
|
|
missions : [],
|
|
now : new Date(),
|
|
timer: null,
|
|
misi:[],
|
|
logs:[]
|
|
};
|
|
},
|
|
methods: {
|
|
clickCharacter(char) {
|
|
this.selectedCharacter = char;
|
|
this.showModal = false;
|
|
},
|
|
changeAva(type) {
|
|
this.modalType = type;
|
|
this.showModal = true;
|
|
},
|
|
profileListSelected(profile) {
|
|
this.selectedProfile = profile;
|
|
this.showModal = false;
|
|
},
|
|
async getMission() {
|
|
const res = await getMissions();
|
|
this.missions = res.results;
|
|
console.log(this.missions);
|
|
},
|
|
async getLogs(){
|
|
const resLog = await getMissionLogs();
|
|
this.logs = resLog.results;
|
|
},
|
|
timeLeft2(dateValid, timeToValid) {
|
|
if (!dateValid || !timeToValid) return "—";
|
|
try {
|
|
const now = new Date(this.now);
|
|
const target = new Date(`${dateValid}T${timeToValid}`);
|
|
const diffMs = target - now;
|
|
if (diffMs <= 0) return "Waktu habis";
|
|
|
|
const totalMinutes = Math.floor(diffMs / (1000 * 60));
|
|
const hours = Math.floor(totalMinutes / 60);
|
|
const minutes = totalMinutes % 60;
|
|
return `${hours} jam ${minutes} menit`;
|
|
} catch (e) {
|
|
return "—";
|
|
}
|
|
},
|
|
timeLeft(dateValid, timeToValid) {
|
|
if (!dateValid || !timeToValid) return "—";
|
|
|
|
const now = new Date(this.now);
|
|
const target = new Date(`${dateValid}T${timeToValid}`);
|
|
const diffMs = target - now;
|
|
|
|
if (diffMs <= 0) return "Waktu habis";
|
|
|
|
const totalSeconds = Math.floor(diffMs / 1000);
|
|
const hours = Math.floor(totalSeconds / 3600);
|
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
const seconds = totalSeconds % 60;
|
|
|
|
const pad = (num) => String(num).padStart(2, '0');
|
|
|
|
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
|
},
|
|
downtimeHours(from, to) {
|
|
if (!from || !to) return '-';
|
|
const [fh, fm] = from.split(':').map(Number);
|
|
const [th, tm] = to.split(':').map(Number);
|
|
const start = fh * 60 + fm;
|
|
const end = th * 60 + tm;
|
|
const diff = end - start;
|
|
const hours = (diff / 60).toFixed(2);
|
|
return hours;
|
|
},
|
|
async getMissions() {
|
|
const [resMissions, resLogs] = await Promise.all([
|
|
getMissions(),
|
|
getMissionLogs()
|
|
]);
|
|
|
|
const logs = resLogs.results || [];
|
|
this.misi = resMissions.results.map(mission => {
|
|
const log = logs.find(l => l.mission === mission.id) || {};
|
|
return {
|
|
...mission,
|
|
user_id: log.user_id || null,
|
|
userStatus: log.status || 'not_started', // status default
|
|
claimed_at: log.claimed_at || null,
|
|
completed_at: log.completed_at || null,
|
|
coin_earned: log.coin || mission.coin,
|
|
point_earned: log.point || mission.point,
|
|
image_log: log.image_log || null,
|
|
};
|
|
});
|
|
this.missions = this.misi
|
|
},
|
|
handleMissionClick(mission) {
|
|
//convert to array task
|
|
const missionWithTask = {
|
|
...mission,
|
|
tasks:[
|
|
{id: mission.id,name:mission.name, type: mission.task, completed:false}
|
|
]
|
|
}
|
|
if (mission.userStatus === 'completed') return;
|
|
if (mission.userStatus === 'not_started') {
|
|
this.startMission(mission);
|
|
}
|
|
if (mission.task === 'scan-qr') {
|
|
console.log(mission)
|
|
this.$router.push({
|
|
name: 'quest-missions',
|
|
params: { id: mission.id } ,
|
|
query: { mission: JSON.stringify(missionWithTask) }
|
|
});
|
|
} else {
|
|
this.$router.push({
|
|
name: 'quest-missions',
|
|
params: { id: mission.id } ,
|
|
query: { mission: JSON.stringify(missionWithTask) }
|
|
});
|
|
}
|
|
},
|
|
|
|
async startMission(mission) {
|
|
await createMissionLog({
|
|
mission: mission.id,
|
|
user_id: this.currentUser.id,
|
|
status: 'in_progress',
|
|
coin: mission.coin,
|
|
point: mission.point
|
|
});
|
|
|
|
mission.userStatus = 'in_progress';
|
|
}
|
|
},
|
|
mounted() {
|
|
this.getMission();
|
|
this.getMissions();
|
|
this.timer = setInterval(() => {
|
|
this.now = Date.now();
|
|
}, 1000);
|
|
},
|
|
|
|
beforeUnmount() {
|
|
clearInterval(this.timer);
|
|
},
|
|
};
|
|
</script>
|
|
<script setup>
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import { useRouter } from 'vue-router'
|
|
const router = useRouter()
|
|
const auth = useAuthStore()
|
|
const handleLogout = () => {
|
|
auth.logout()
|
|
router.push('/login')
|
|
}
|
|
</script> |