loagin animation and remove storage
This commit is contained in:
parent
59fa8d61c9
commit
581ecdc534
35
package-lock.json
generated
35
package-lock.json
generated
@ -10,11 +10,13 @@
|
||||
"dependencies": {
|
||||
"axios": "^1.12.2",
|
||||
"core-js": "^3.46.0",
|
||||
"lottie-web": "^5.13.0",
|
||||
"pinia": "^3.0.3",
|
||||
"primeicons": "^7.0.0",
|
||||
"vue": "^3.2.13",
|
||||
"vue-qrcode-reader": "^5.7.3",
|
||||
"vue-router": "^4.5.1"
|
||||
"vue-router": "^4.5.1",
|
||||
"vue3-lottie": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.16",
|
||||
@ -6700,7 +6702,6 @@
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
@ -8249,7 +8250,6 @@
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
|
||||
"integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
@ -8820,6 +8820,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/lottie-web": {
|
||||
"version": "5.13.0",
|
||||
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.13.0.tgz",
|
||||
"integrity": "sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lower-case": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
||||
@ -13070,6 +13076,29 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vue3-lottie": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/vue3-lottie/-/vue3-lottie-3.3.1.tgz",
|
||||
"integrity": "sha512-60uQmx4eefi3FdPjAxWnblrgJJjnVTXUA6e4BAI3jGzgOSR76pyzL1rrWDiyPmMFo4mTw4wGTW6Gbkg3HR1mYw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"klona": "^2.0.6",
|
||||
"lottie-web": "5.12.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/vue3-lottie/node_modules/lottie-web": {
|
||||
"version": "5.12.2",
|
||||
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz",
|
||||
"integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
||||
|
||||
@ -11,11 +11,13 @@
|
||||
"dependencies": {
|
||||
"axios": "^1.12.2",
|
||||
"core-js": "^3.46.0",
|
||||
"lottie-web": "^5.13.0",
|
||||
"pinia": "^3.0.3",
|
||||
"primeicons": "^7.0.0",
|
||||
"vue": "^3.2.13",
|
||||
"vue-qrcode-reader": "^5.7.3",
|
||||
"vue-router": "^4.5.1"
|
||||
"vue-router": "^4.5.1",
|
||||
"vue3-lottie": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.16",
|
||||
|
||||
BIN
public/images/loading.gif
Normal file
BIN
public/images/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
1
public/images/loading.json
Normal file
1
public/images/loading.json
Normal file
File diff suppressed because one or more lines are too long
BIN
src/assets/images/loading.gif
Normal file
BIN
src/assets/images/loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
1
src/assets/images/loading.json
Normal file
1
src/assets/images/loading.json
Normal file
File diff suppressed because one or more lines are too long
1
src/assets/images/loading1.json
Normal file
1
src/assets/images/loading1.json
Normal file
File diff suppressed because one or more lines are too long
47
src/components/Loading.vue
Normal file
47
src/components/Loading.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div v-if="show" class="overlay">
|
||||
<Vue3Lottie
|
||||
:animationData="animation"
|
||||
:height="200"
|
||||
:width="200"
|
||||
autoplay
|
||||
loop
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Vue3Lottie } from "vue3-lottie";
|
||||
import animation from "@/assets/images/loading.json";
|
||||
|
||||
export default {
|
||||
name: "LoadingComponent",
|
||||
components: { Vue3Lottie },
|
||||
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
animation
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(1px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
</style>
|
||||
@ -3,7 +3,8 @@ import App from './App.vue'
|
||||
import './assets/tailwind.css'
|
||||
import router from './router'
|
||||
import { createPinia } from 'pinia'
|
||||
import Vue3Lottie from 'vue3-lottie'
|
||||
|
||||
const pinia = createPinia()
|
||||
createApp(App).use(pinia).use(router).mount('#app')
|
||||
createApp(App).use(pinia).use(router).use(Vue3Lottie).mount('#app')
|
||||
|
||||
|
||||
@ -112,7 +112,6 @@ export default {
|
||||
if (this.pages.length > 0 && this.pages[0].chapter?.manga?.title) {
|
||||
this.mangaTitle = this.pages[0].chapter.manga.title
|
||||
}
|
||||
console.log("Pages :" + JSON.stringify(this.pages))
|
||||
} catch (err) {
|
||||
console.error("Gagal memuat halaman:", err)
|
||||
} finally {
|
||||
|
||||
@ -100,13 +100,8 @@ export default {
|
||||
async loadContent() {
|
||||
const res = await getChapters(this.id);
|
||||
this.chapters = res.results;
|
||||
|
||||
console.log(this.id)
|
||||
console.log(this.props)
|
||||
console.log(res.results);
|
||||
},
|
||||
toSynopsis( manga) {
|
||||
console.log(manga)
|
||||
router.push({
|
||||
name: 'manga-sinopsis',
|
||||
params: { id: manga.id },
|
||||
|
||||
@ -136,7 +136,6 @@ export default {
|
||||
async loadGenres() {
|
||||
const res = await getGenre();
|
||||
this.genres = res.results;
|
||||
console.log(res);
|
||||
},
|
||||
onMouseMove(event, name) {
|
||||
const card = event.currentTarget;
|
||||
|
||||
@ -511,7 +511,6 @@ export default {
|
||||
},
|
||||
async myPoints(){
|
||||
const points = await getUserPoint();
|
||||
// console.log(points)
|
||||
this.points = points.myPoints;
|
||||
this.totalTask = points.activeTaskCount;
|
||||
this.totalDone = points.myActiveTaskCompleteCount;
|
||||
@ -529,7 +528,7 @@ export default {
|
||||
|
||||
try {
|
||||
const start = new Date(dateValidFrom);
|
||||
const end = new Date(dateValidTo); // Already UTC-aware
|
||||
const end = new Date(dateValidTo);
|
||||
const now = new Date(this.now);
|
||||
|
||||
const diffToStart = start - now;
|
||||
@ -543,8 +542,6 @@ export default {
|
||||
const seconds = totalSeconds % 60;
|
||||
return `⏳ ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
||||
}
|
||||
|
||||
// 🟢 During event
|
||||
if (diffToEnd > 0) {
|
||||
const totalSeconds = Math.floor(diffToEnd / 1000);
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
@ -578,8 +575,6 @@ export default {
|
||||
},
|
||||
timeLeft(dateFrom, dateTo, timeFrom, timeTo) {
|
||||
if (!dateFrom || !timeFrom || !dateTo || !timeTo) return "—";
|
||||
|
||||
// const now = new Date();
|
||||
const start = new Date(`${dateFrom}T${timeFrom}`);
|
||||
const end = new Date(`${dateTo}T${timeTo}`);
|
||||
const current = this.now;
|
||||
@ -587,8 +582,6 @@ export default {
|
||||
const pad = (num) => String(num).padStart(2, "0");
|
||||
const diffToStart = start - current;
|
||||
const diffToEnd = end - current;
|
||||
|
||||
// 🕰️ CASE 1: Before start
|
||||
if (diffToStart > 0) {
|
||||
const totalSeconds = Math.floor(diffToStart / 1000);
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
@ -605,7 +598,6 @@ export default {
|
||||
|
||||
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
||||
}
|
||||
// ⛔ CASE 3: After end
|
||||
return "❌ Waktu habis";
|
||||
},
|
||||
downtimeHours(from, to) {
|
||||
@ -652,7 +644,6 @@ export default {
|
||||
// this.startMission(mission);
|
||||
}
|
||||
if (mission.task === 'scan-qr') {
|
||||
console.log(mission)
|
||||
this.$router.push({
|
||||
name: 'quest-missions',
|
||||
params: { id: mission.id } ,
|
||||
@ -669,7 +660,6 @@ export default {
|
||||
|
||||
async startMission(mission) {
|
||||
if (!mission || !mission.id) {
|
||||
console.error("Invalid mission", mission);
|
||||
return;
|
||||
}
|
||||
await createMissionLog({
|
||||
@ -707,7 +697,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
currentUser() {
|
||||
console.log(this.authStore.currentUser)
|
||||
return this.authStore.currentUser;
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<LoadingComponent :show="isLoading" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -87,6 +88,7 @@ export default {
|
||||
],
|
||||
selectedCharacter: { name: "Tiger", img: "../images/char/tiger.png" },
|
||||
selectedProfile: { name: "profile", img: "/images/propic-001.svg" },
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -110,20 +112,25 @@ export default {
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
import LoadingComponent from '@/components/Loading.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
const username = ref('')
|
||||
const password = ref('')
|
||||
const error = ref('')
|
||||
const isLoading = ref(false)
|
||||
|
||||
async function login() {
|
||||
try {
|
||||
await
|
||||
isLoading.value = true
|
||||
await auth.login(username.value, password.value)
|
||||
|
||||
router.push('/')
|
||||
} catch (err) {
|
||||
error.value = err.message
|
||||
}finally{
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -133,4 +140,19 @@ async function login() {
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
#loading {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
}
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -157,7 +157,6 @@
|
||||
onMounted(async () => {
|
||||
if(router.query.mission){
|
||||
const data = router.query.mission
|
||||
console.log(data)
|
||||
mission.value = JSON.parse(data)
|
||||
}
|
||||
|
||||
|
||||
@ -15,16 +15,13 @@ export const useAuthStore = defineStore('auth', {
|
||||
},
|
||||
actions: {
|
||||
async register(username, password, re_password) {
|
||||
const response =await axios.post(this.baseUrl + '/auth/users/', {
|
||||
return await axios.post(this.baseUrl + '/auth/users/', {
|
||||
username: username,
|
||||
password: password,
|
||||
re_password: re_password
|
||||
});
|
||||
|
||||
console.log("✅ Registration success:", response.data);
|
||||
},
|
||||
async login(username, password) {
|
||||
// preparing data
|
||||
const data = new URLSearchParams()
|
||||
data.append('grant_type', 'password')
|
||||
data.append('client_id', this.clientId)
|
||||
@ -35,7 +32,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
const response = await axios.post(`${this.baseUrl}`+'/oauth/token/',data.toString(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
},
|
||||
withCredentials:true,
|
||||
})
|
||||
|
||||
const { access_token, refresh_token } = response.data;
|
||||
@ -48,11 +46,24 @@ export const useAuthStore = defineStore('auth', {
|
||||
this.refresh_token = refresh_token
|
||||
this.token = access_token
|
||||
this.user = user
|
||||
await this.fetchUser();
|
||||
// localStorage.setItem('token', this.token)
|
||||
// localStorage.setItem('user', JSON.stringify(user))
|
||||
},
|
||||
async fetchUser() {
|
||||
try {
|
||||
const res = await axios.get(`${this.baseUrl}/auth/users/me`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.token}`,
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(user));
|
||||
localStorage.setItem('token', this.token)
|
||||
localStorage.setItem('user', JSON.stringify(user))
|
||||
console.log("✅ Logged in as:", this.user.username);
|
||||
this.user = res.data;
|
||||
} catch (err) {
|
||||
console.error("❌ fetch user failed", err);
|
||||
this.user = null;
|
||||
}
|
||||
},
|
||||
async logout() {
|
||||
if(this.token){
|
||||
@ -63,6 +74,7 @@ export const useAuthStore = defineStore('auth', {
|
||||
},
|
||||
{
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
withCredentials:true
|
||||
});
|
||||
}else{
|
||||
console.log("No token found");
|
||||
@ -70,16 +82,14 @@ export const useAuthStore = defineStore('auth', {
|
||||
|
||||
this.token = null;
|
||||
this.user = null;
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
// localStorage.removeItem('token')
|
||||
// localStorage.removeItem('user')
|
||||
},
|
||||
restoreSession() {
|
||||
const savedToken = localStorage.getItem('token')
|
||||
const savedUser = localStorage.getItem('user')
|
||||
|
||||
if (savedToken && savedUser) {
|
||||
this.token = savedToken
|
||||
this.user = JSON.parse(savedUser)
|
||||
async restoreSession() {
|
||||
try {
|
||||
await this.fetchUser();
|
||||
} catch {
|
||||
console.log("No active session found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user