I am setting up a vuejs application that should route to some predefined pages.
All the routes work perfect, except “complete” and “allCompleted”
When all the quests are completed, the user should be redirected to the allCompleted route.
What the actual result is:
When a user completes a quest, the app gets redirected to “complete”. But this renders the allCompleted component.
When all quests are completed, we get redirected to “allCompleted”.
So I don’t know what I’m doing wrong.
We think we’ve read every post on the internet regarding vue-router and rendering wrong components and most of them are about typo’s or rendering children in a sub-router-view. But this is not the case in our application.
router.ts
import Vue from "vue";
import Router from "vue-router";
import { QuestsView, QuestCompleteView } from "@/modules/quests";
import QuestDetailView from "../modules/quests/views/QuestDetailView.vue";
import QuestAllCompletedView from "../modules/quests/views/QuestAllCompletedView.vue";
import Register from "../modules/auth/components/Register.vue";
import Login from "../modules/auth/components/Login.vue";
import PasswordForgotten from "../modules/auth/components/PasswordForgotten.vue";
import ContactsView from "../modules/contacts/views/ContactsView.vue";
import authGuard from "./auth-guard";
import LeaderBoardView from "@/modules/leaderboard/views/LeaderBoardView.vue";
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "*",
redirect: "/quests"
},
{
path: "/register",
name: "register",
component: Register
},
{
path: "/login",
name: "login",
component: Login
},
{
path: "/passwordForgotten",
name: "passwordForgotten",
component: PasswordForgotten
},
{
path: "/quests",
name: "quests",
component: QuestsView,
beforeEnter: authGuard
},
{
path: "/quests/:id",
name: "quest detail",
component: QuestDetailView,
beforeEnter: authGuard
},
{
path: "/contacts",
name: "contacts",
component: ContactsView,
beforeEnter: authGuard
},
{
path: "/info",
name: "info",
beforeEnter: authGuard
},
{
path: "/leaderboard",
name: "leaderboard",
component: LeaderBoardView,
beforeEnter: authGuard
},
{
path: "/complete",
name: "complete",
component: QuestCompleteView,
},
{
path: "/allCompleted",
name: "allCompleted",
component: QuestAllCompletedView
}
]
});
QuestList.vue
export default class Quests extends Vue {
@QuestsGetter quests: Quest[];
@QuestsGetter loading: boolean;
@QuestsAction loadQuests;
@Watch("quests")
onQuestsChange(value: Quest[]): void {
const completedQuests = value.filter(
quest => quest.status === QuestStatus.COMPLETED
);
if (completedQuests.length === this.quests.length) {
this.$router.push("/allCompleted"); // Todo: Create allCompleted view
}
}
created() {
this.loadQuests();
}
}
</script>
QuestAllCompletedView.vue
<template>
<div class="quest-all-complete-view">
<router-link to="quests">
<div class="all-reward all-reward--image"></div>
</router-link>
</div>
</template>
<script lang="ts">
import { Vue } from "vue-property-decorator";
export default class QuestAllCompletedView extends Vue {}
</script>
<style scoped lang="scss">
@import "~@/styles/variables";
.quest-all-complete-view {
width: 100%;
.all-reward {
width: auto;
height: 56rem;
&--image {
background: url("~@/assets/images/reward-starburst-final.png") center
center / contain no-repeat;
}
}
.back-to-overview {
height: 4rem;
display: block;
margin: -140px auto 0 auto;
&--image {
background: url("~@/assets/images/backtooverview.png") center center /
contain no-repeat;
}
}
}
</style>
QuestCompleteView.vue
<template>
<div class="quest-complete-view">
<div class="reward reward--image"></div>
<router-link to="quests">
<div class="back-to-overview back-to-overview--image"></div>
</router-link>
</div>
</template>
<script lang="ts">
import { Vue } from "vue-property-decorator";
export default class QuestComplete extends Vue {}
</script>
<style scoped lang="scss">
@import "~@/styles/variables";
.quest-complete-view {
width: 100%;
.reward {
width: auto;
height: 56rem;
&--image {
background: url("~@/assets/images/reward.png") center center / contain
no-repeat;
}
}
.back-to-overview {
height: 4rem;
display: block;
margin: -140px auto 0 auto;
&--image {
background: url("~@/assets/images/backtooverview.png") center center /
contain no-repeat;
}
}
}
</style>
Auth-guard
import store from "@/store/index";
export default (to: any, from: any, next: any) => {
if (store.state.auth.user) {
next();
} else {
next("/login");
}
};
Part of the code in the QuestDetailView.vue that routes to /complete
public handleButtonClick(): void {
if (this.quest.status === QuestStatus.UNCOMPLETED) {
this.startQuest(this.quest.id).then(() => this.$router.push("/quests"));
} else if (this.quest.status === QuestStatus.IN_PROGRESS) {
this.stopQuest(this.quest.id).then(() => this.$router.push("/complete"));
}
}
So what we want is that:
When we route to the /complete route, it renders the Questcomplete component, being “QuestCompleteView”
When we do render.push("/allCompleted"), we go to the allCompleted route with the correct component, being QuestAllCompletedView