Skip to content
Snippets Groups Projects
Commit 815b3603 authored by Henrik Teksle Sandok's avatar Henrik Teksle Sandok
Browse files

Merge branch 'Premium' into 'main'

Premium

See merge request !60
parents 2999ede5 ea1e9c33
No related branches found
No related tags found
1 merge request!60Premium
Pipeline #281918 passed with warnings
......@@ -70,7 +70,7 @@
<li><router-link data-cy="profile"
class="dropdown-item text-white dropdown-username-link" :to="toUserProfile()"><img
src="@/assets/icons/person.svg">User Profile</router-link></li>
<li><router-link data-cy="budget"
<li v-if="useUserInfoStore().isPremium"><router-link data-cy="budget"
class="dropdown-item text-white dropdown-username-link" :to="toBudget()"><img>Budget</router-link></li>
<li><router-link data-cy="friends"
class="dropdown-item text-white dropdown-username-link" :to="toFriends()"><img
......
......@@ -57,7 +57,7 @@ console.log(props.leaderboardExtra);
const userInLeaderboard = computed(() => props.leaderboard.some(entry => entry.user && entry.user.email === userStore.email));
const navigateToUserProfile = (id: number) => {
router.push({ name: 'user-profile' });
router.push(`/profile/${id}`);
};
</script>
......
......@@ -47,7 +47,6 @@ const handleSubmit = async () => {
try {
let response = await AuthenticationService.login({ requestBody: loginUserPayload });
if (response.token == null || response.token == undefined) {
errorMsg.value = 'A valid token could not be created';
return;
......@@ -62,11 +61,9 @@ const handleSubmit = async () => {
lastname: response.lastName,
email: emailRef.value,
role: response.role,
subscriptionLevel: response.subscriptionLevel,
profileImage: response.profileImage
});
console.log()
await router.push({ name: 'home' });
} catch (error: any) {
errorMsg.value = handleUnknownError(error);
......
......@@ -95,11 +95,13 @@ const routes = [
path: '/budget-overview',
name: 'budget overview',
component: () => import('@/views/Budget/BudgetOverview.vue'),
meta: { requiresPremium: true },
},
{
path: '/budget',
name: 'budget',
component: () => import('@/views/Budget/BudgetView.vue'),
meta: { requiresPremium: true },
},
{
path: '/profile/:id',
......@@ -203,14 +205,18 @@ const router = createRouter({
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const requiresAdmin = to.matched.some(record => record.meta.requiresAdmin);
const user= useUserInfoStore();
const requiresPremium = to.matched.some(record => record.meta.requiresPremium);
const user = useUserInfoStore();
const userRole = user.role;
const userSubscription = user.subscriptionLevel;
const isAuthenticated = user.isLoggedIn;
if (requiresAuth && !isAuthenticated) {
next({ name: 'login', query: { redirect: to.fullPath } });
} else if (requiresAdmin && userRole !== 'admin') {
next({ name: 'unauthorized' });
} else if (requiresPremium && userSubscription !== 'PREMIUM') {
next({ name: 'home' });
} else {
next();
}
......
......@@ -36,9 +36,10 @@ export type UserStoreInfo = {
password?: string;
accessToken?: string;
role?: string;
subscriptionLevel?: string;
profileImage?: number;
};
//todo Fix if there is time
export const useUserInfoStore = defineStore('UserInfoStore', {
state: () => ({
id: 0,
......@@ -48,6 +49,7 @@ export const useUserInfoStore = defineStore('UserInfoStore', {
password: '',
accessToken: '',
role: '',
subscriptionLevel: '',
profileImage: 0,
}),
persist: {
......@@ -68,6 +70,7 @@ export const useUserInfoStore = defineStore('UserInfoStore', {
userinfo.accessToken && (this.$state.accessToken = userinfo.accessToken);
userinfo.accessToken && (OpenAPI.TOKEN = this.$state.accessToken);
userinfo.role && (this.$state.role = userinfo.role);
userinfo.subscriptionLevel && (this.$state.subscriptionLevel = userinfo.subscriptionLevel);
userinfo.profileImage && (this.$state.profileImage = userinfo.profileImage);
},
clearUserInfo() {
......@@ -77,6 +80,7 @@ export const useUserInfoStore = defineStore('UserInfoStore', {
this.$state.lastname = '';
this.$state.accessToken = '';
this.$state.role = '';
this.$state.subscriptionLevel = '';
this.$state.profileImage = 0;
OpenAPI.TOKEN = undefined;
},
......@@ -97,5 +101,11 @@ export const useUserInfoStore = defineStore('UserInfoStore', {
isLoggedIn(): boolean {
return this.accessToken !== '';
},
isPremium(): boolean {
return this.subscriptionLevel === 'PREMIUM';
},
isNoAds(): boolean {
return this.subscriptionLevel === 'NO_ADS';
}
},
});
\ No newline at end of file
......@@ -3,18 +3,18 @@ import { RouterView } from 'vue-router'
import Footer from '@/components/BaseComponents/Footer.vue'
import Menu from '@/components/BaseComponents/Menu.vue'
import FooterAlternative from "@/components/BaseComponents/FooterAlternative.vue";
import { useUserInfoStore } from '@/stores/UserStore';
</script>
<template>
<Menu data-cy="menu"></Menu>
<div style="display: flex; flex-direction: row;">
<div v-if="!useUserInfoStore().isPremium && !useUserInfoStore().isNoAds" style="display: flex; flex-direction: row;">
<img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;" alt="picture">
</div>
<div>
<RouterView />
</div>
<div style="display: flex; flex-direction: row;">
<div v-if="!useUserInfoStore().isPremium && !useUserInfoStore().isNoAds" style="display: flex; flex-direction: row;">
<img v-for="item in 7" src="@/assets/coca.webp" style="width: 100%; height: 100px; margin: 5px; border-radius: 1rem;" alt="picture">
</div>
<FooterAlternative></FooterAlternative>
......
......@@ -12,16 +12,17 @@
<img src="@/assets/items/adfree.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Adfree</h5>
<button type="button" class="btn btn-primary" id="buttonStyle"> +35kr</button>
<button type="button" class="btn btn-primary" id="buttonStyle" @click="buyNoAds"> +35kr</button>
</div>
</div>
</div>
<div class="card text-center" style="width: 16rem; border: none">
<img src="@/assets/items/piggybank.webp" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Premium</h5>
<button type="button" class="btn btn-primary" id="buttonStyle">+50kr</button>
<button type="button" class="btn btn-primary" id="buttonStyle"
@click="buyPremium">+50kr</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
......@@ -68,21 +69,21 @@
<h5 class="card-title">Free Coffee</h5>
<ShopButton button-text="500"></ShopButton>
</div>
</div>
</div>
<div class="card text-center" style="width: 16rem; border: none">
<img src="@/assets/items/viaplay.jpg" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">1 Month Viaplay</h5>
<ShopButton button-text="10000"></ShopButton>
</div>
</div>
</div>
<div class="card text-center" style="width: 16rem; border: none">
<img src="@/assets/items/pirbad.png" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">-10% rabatt</h5>
<ShopButton button-text="1000"></ShopButton>
</div>
</div>
</div>
</div>
</div>
......@@ -92,6 +93,31 @@
<script setup lang="ts">
import ShopButton from '@/components/Buttons/ShopButton.vue';
import { ref } from 'vue';
import { UserService } from '@/api';
import { useUserInfoStore } from '@/stores/UserStore';
const buyPremium = async () => {
try {
const response = await UserService.updateSubscriptionLevel({ subscriptionLevel: 'PREMIUM' });
useUserInfoStore().setUserInfo({
subscriptionLevel: 'PREMIUM',
})
} catch (error) {
console.log(error);
}
}
const buyNoAds = async () => {
try {
const response = await UserService.updateSubscriptionLevel({ subscriptionLevel: 'NO_ADS' });
useUserInfoStore().setUserInfo({
subscriptionLevel: 'NO_ADS',
})
} catch (error) {
console.log(error);
}
}
</script>
<style scoped>
......@@ -105,14 +131,14 @@ import ShopButton from '@/components/Buttons/ShopButton.vue';
}
.box {
width:90%;
width: 90%;
}
.card:hover {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.card-body{
.card-body {
height: 100px;
padding: 5px;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment