Move session management to sessionStore.
This commit is contained in:
parent
074fce7498
commit
6d2df5d44a
10 changed files with 105 additions and 73 deletions
|
|
@ -5,19 +5,19 @@ import { RouterView } from 'vue-router'
|
||||||
import Footer from "@/components/Footer.vue";
|
import Footer from "@/components/Footer.vue";
|
||||||
import Sidebar from "@/components/Sidebar.vue";
|
import Sidebar from "@/components/Sidebar.vue";
|
||||||
import TopBar from "@/components/TopBar.vue";
|
import TopBar from "@/components/TopBar.vue";
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const sessionStore = useSessionStore();
|
||||||
|
|
||||||
const sidebarSize = computed(() => {
|
const sidebarSize = computed(() => {
|
||||||
return userStore.isAnonymous ? '0' : '90px';
|
return sessionStore.isAnonymous ? '0' : '90px';
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="act-layout">
|
<div class="act-layout">
|
||||||
<TopBar class="act-header"></TopBar>
|
<TopBar class="act-header"></TopBar>
|
||||||
<div class="act-sidebar" v-if="!userStore.isAnonymous">
|
<div class="act-sidebar" v-if="!sessionStore.isAnonymous">
|
||||||
<Sidebar></Sidebar>
|
<Sidebar></Sidebar>
|
||||||
</div>
|
</div>
|
||||||
<div class="act-content">
|
<div class="act-content">
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,15 @@ import Avatar from 'primevue/avatar';
|
||||||
import Menu from "primevue/menu";
|
import Menu from "primevue/menu";
|
||||||
|
|
||||||
import { userActions } from "@/stores/userActionsStore";
|
import { userActions } from "@/stores/userActionsStore";
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
import Navigation from "@/components/Navigation.vue";
|
import Navigation from "@/components/Navigation.vue";
|
||||||
|
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const sessionStore = useSessionStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
userStore.logout();
|
sessionStore.logout();
|
||||||
};
|
};
|
||||||
const profile = () => {
|
const profile = () => {
|
||||||
router.push({name: "profile"});
|
router.push({name: "profile"});
|
||||||
|
|
@ -42,13 +42,13 @@ const toggle = (event) => { menu.value.toggle(event); };
|
||||||
<Navigation></Navigation>
|
<Navigation></Navigation>
|
||||||
<div class="mt-auto act-avatar">
|
<div class="mt-auto act-avatar">
|
||||||
<a class="nav-item" @click="toggle">
|
<a class="nav-item" @click="toggle">
|
||||||
<div v-if="userStore.isAnonymous">
|
<div v-if="sessionStore.isAnonymous">
|
||||||
<Avatar icon="pi pi-user" size="large" shape="circle" />
|
<Avatar icon="pi pi-user" size="large" shape="circle" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<Avatar v-bind:label="userStore.initials" size="large" shape="circle" />
|
<Avatar v-bind:label="sessionStore.initials" size="large" shape="circle" />
|
||||||
</div>
|
</div>
|
||||||
<span class="inline lg:hidden">{{ userStore.user.name }}</span>
|
<span class="inline lg:hidden">{{ sessionStore.user.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true">
|
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true">
|
||||||
<template #item="{ item, props }">
|
<template #item="{ item, props }">
|
||||||
|
|
@ -56,7 +56,7 @@ const toggle = (event) => { menu.value.toggle(event); };
|
||||||
class="flex items-center"
|
class="flex items-center"
|
||||||
v-bind:class="{ 'act-useraction': item.needsAuth }"
|
v-bind:class="{ 'act-useraction': item.needsAuth }"
|
||||||
v-bind="props.action"
|
v-bind="props.action"
|
||||||
v-if="!item.needsAuth || !userStore.isAnonymous">
|
v-if="!item.needsAuth || !sessionStore.isAnonymous">
|
||||||
<span v-bind:class="item.icon" />
|
<span v-bind:class="item.icon" />
|
||||||
<span>{{ item.label }}</span>
|
<span>{{ item.label }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { ref, watch } from 'vue';
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
import { userActions } from "@/stores/userActionsStore";
|
import { userActions } from "@/stores/userActionsStore";
|
||||||
|
|
||||||
import Button from 'primevue/button';
|
import Button from 'primevue/button';
|
||||||
|
|
@ -13,7 +13,7 @@ import Menu from "primevue/menu";
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const page_title = ref();
|
const page_title = ref();
|
||||||
const userStore = useUserStore();
|
const sessionStore = useSessionStore();
|
||||||
|
|
||||||
watch(() => route.meta, (newVal, oldVal) => {
|
watch(() => route.meta, (newVal, oldVal) => {
|
||||||
page_title.value = newVal.title;
|
page_title.value = newVal.title;
|
||||||
|
|
@ -23,7 +23,7 @@ const toggle = (event) => {
|
||||||
menu.value.toggle(event);
|
menu.value.toggle(event);
|
||||||
};
|
};
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
userStore.logout();
|
sessionStore.logout();
|
||||||
};
|
};
|
||||||
const profile = () => {
|
const profile = () => {
|
||||||
router.push({name: "profile"});
|
router.push({name: "profile"});
|
||||||
|
|
@ -79,7 +79,7 @@ const items = ref(allActions);
|
||||||
<Button
|
<Button
|
||||||
as="router-link"
|
as="router-link"
|
||||||
:to="{name: 'login', query: {next: route.fullPath }}"
|
:to="{name: 'login', query: {next: route.fullPath }}"
|
||||||
v-if="userStore.isAnonymous">
|
v-if="sessionStore.isAnonymous">
|
||||||
<i class="pi pi-sign-in" />
|
<i class="pi pi-sign-in" />
|
||||||
<span>Login</span>
|
<span>Login</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -108,7 +108,7 @@ const items = ref(allActions);
|
||||||
class="flex items-center"
|
class="flex items-center"
|
||||||
v-bind:class="{ 'act-useraction': item.needsAuth }"
|
v-bind:class="{ 'act-useraction': item.needsAuth }"
|
||||||
v-bind="props.action"
|
v-bind="props.action"
|
||||||
v-if="!item.needsAuth || !userStore.isAnonymous">
|
v-if="!item.needsAuth || !sessionStore.isAnonymous">
|
||||||
<span v-bind:class="item.icon" />
|
<span v-bind:class="item.icon" />
|
||||||
<span>{{ item.label }}</span>
|
<span>{{ item.label }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
import AboutView from '../views/AboutView.vue'
|
import AboutView from '../views/AboutView.vue'
|
||||||
import HomeView from '../views/HomeView.vue'
|
import HomeView from '../views/HomeView.vue'
|
||||||
import LoginView from '../views/LoginView.vue'
|
import LoginView from '../views/LoginView.vue'
|
||||||
|
|
@ -73,18 +73,18 @@ const router = createRouter({
|
||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach((to, from) => {
|
router.beforeEach((to, from) => {
|
||||||
const userStore= useUserStore();
|
const sessionStore= useSessionStore();
|
||||||
if (userStore.isAnonymous && to.name == 'home') {
|
if (sessionStore.isAnonymous && to.name == 'home') {
|
||||||
return {name: 'welcome'};
|
return {name: 'welcome'};
|
||||||
} else if (!userStore.isAnonymous && to.name == 'welcome') {
|
} else if (!sessionStore.isAnonymous && to.name == 'welcome') {
|
||||||
return {name: 'home'};
|
return {name: 'home'};
|
||||||
} else if (to.name == 'profile' && to.params.username == "") {
|
} else if (to.name == 'profile' && to.params.username == "") {
|
||||||
if (userStore.isAnonymous) {
|
if (sessionStore.isAnonymous) {
|
||||||
return {name: 'home'};
|
return {name: 'home'};
|
||||||
} else {
|
} else {
|
||||||
// Send to "my" profile page.
|
// Send to "my" profile page.
|
||||||
return {name: 'profile', params: {
|
return {name: 'profile', params: {
|
||||||
username: userStore.user.username,
|
username: sessionStore.user.username,
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
src/stores/sessionStore.ts
Normal file
65
src/stores/sessionStore.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import {acceptHMRUpdate, defineStore} from 'pinia'
|
||||||
|
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
name: string,
|
||||||
|
sticker_ids: string[],
|
||||||
|
username: string | null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const anonymous: User = {
|
||||||
|
name: 'Anonymous',
|
||||||
|
sticker_ids: [],
|
||||||
|
username: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
user: User,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSessionStore = defineStore('session', {
|
||||||
|
actions: {
|
||||||
|
async login(username: string, password: string) {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/login/${username}`, // TODO: Should not be in path.
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const json = await response.json();
|
||||||
|
console.log('login', json);
|
||||||
|
// this.user.name = json.name;
|
||||||
|
this.user = {
|
||||||
|
name: json.name,
|
||||||
|
sticker_ids: json.sticker_ids,
|
||||||
|
username: json.username,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
console.log('logout');
|
||||||
|
// TODO: Tell server.
|
||||||
|
this.user = anonymous;
|
||||||
|
// this.hasChanged = true;
|
||||||
|
// this.user.name = 'Anonymous';
|
||||||
|
// this.$reset();
|
||||||
|
// this.$patch({user: anonymous});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
initials: (state: State): string => {
|
||||||
|
return state.user.name[0] || '';
|
||||||
|
},
|
||||||
|
isAnonymous: (state: State): boolean => {
|
||||||
|
return state.user.name === 'Anonymous';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: (): State => {
|
||||||
|
return {
|
||||||
|
user: anonymous,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useSessionStore, import.meta.hot))
|
||||||
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ export const useStickerStore = defineStore('sticker', {
|
||||||
}
|
}
|
||||||
this.put(this.sticker.uuid);
|
this.put(this.sticker.uuid);
|
||||||
const userStore= useUserStore();
|
const userStore= useUserStore();
|
||||||
userStore.addSticker(this.sticker.uuid);
|
userStore.addSticker(user.username, this.sticker.uuid);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
state: () => {
|
state: () => {
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,17 @@ export interface User {
|
||||||
username: string | null,
|
username: string | null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const anonymous: User = {
|
|
||||||
name: 'Anonymous',
|
|
||||||
sticker_ids: [],
|
|
||||||
username: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
user: User,
|
|
||||||
users: User[],
|
users: User[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', {
|
export const useUserStore = defineStore('user', {
|
||||||
actions: {
|
actions: {
|
||||||
addSticker(uuid: string) {
|
addSticker(username: string, uuid: string) {
|
||||||
this.user.sticker_ids.push(uuid);
|
let user = this.getUser(username);
|
||||||
|
if (user) {
|
||||||
|
user.sticker_ids.push(uuid);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async fetch(username: string) {
|
async fetch(username: string) {
|
||||||
let user = this.getUser(username);
|
let user = this.getUser(username);
|
||||||
|
|
@ -42,39 +38,8 @@ export const useUserStore = defineStore('user', {
|
||||||
stickersStore.fetch(sticker_id);
|
stickersStore.fetch(sticker_id);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async login(username: string, password: string) {
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/login/${username}`, // TODO: Should not be in path.
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const json = await response.json();
|
|
||||||
console.log('login', json);
|
|
||||||
// this.user.name = json.name;
|
|
||||||
this.user = {
|
|
||||||
name: json.name,
|
|
||||||
sticker_ids: json.sticker_ids,
|
|
||||||
username: json.username,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
logout() {
|
|
||||||
console.log('logout');
|
|
||||||
// TODO: Tell server.
|
|
||||||
this.user = anonymous;
|
|
||||||
// this.hasChanged = true;
|
|
||||||
// this.user.name = 'Anonymous';
|
|
||||||
// this.$reset();
|
|
||||||
// this.$patch({user: anonymous});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
initials: (state: State): string => {
|
|
||||||
return state.user.name[0] || '';
|
|
||||||
},
|
|
||||||
isAnonymous: (state: State): boolean => {
|
|
||||||
return state.user.name === 'Anonymous';
|
|
||||||
},
|
|
||||||
getUser: (state: State) => {
|
getUser: (state: State) => {
|
||||||
return (username: string): User | null => {
|
return (username: string): User | null => {
|
||||||
return state.users.find((user: User) => user.username === username)
|
return state.users.find((user: User) => user.username === username)
|
||||||
|
|
@ -83,7 +48,6 @@ export const useUserStore = defineStore('user', {
|
||||||
},
|
},
|
||||||
state: (): State => {
|
state: (): State => {
|
||||||
return {
|
return {
|
||||||
user: anonymous,
|
|
||||||
users: [],
|
users: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@ import InputText from 'primevue/inputtext';
|
||||||
import Message from 'primevue/message';
|
import Message from 'primevue/message';
|
||||||
import Toast from 'primevue/toast';
|
import Toast from 'primevue/toast';
|
||||||
|
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
|
||||||
|
const sessionStore = useSessionStore();
|
||||||
const username = ref();
|
const username = ref();
|
||||||
const password = ref();
|
const password = ref();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -22,7 +23,7 @@ function handleLogin({ valid }) {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
userStore.login(username.value, username.value).then(() => {
|
sessionStore.login(username.value, username.value).then(() => {
|
||||||
router.push(next);
|
router.push(next);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@ import Panel from 'primevue/panel';
|
||||||
import Timeline from 'primevue/timeline';
|
import Timeline from 'primevue/timeline';
|
||||||
|
|
||||||
import Sticker from "@/components/Sticker.vue";
|
import Sticker from "@/components/Sticker.vue";
|
||||||
|
import {useSessionStore} from "@/stores/sessionStore";
|
||||||
import {type User, useUserStore} from "@/stores/userStore";
|
import {type User, useUserStore} from "@/stores/userStore";
|
||||||
import { useStickersStore } from "@/stores/stickersStore";
|
import { useStickersStore } from "@/stores/stickersStore";
|
||||||
|
|
||||||
|
|
||||||
|
const sessionStore = useSessionStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { getUser } = userStore;
|
const { getUser } = userStore;
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
@ -29,7 +31,7 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const myPage = computed(() => {
|
const myPage = computed(() => {
|
||||||
return !userStore.isAnonymous && userStore.user.username == user?.value.username;
|
return !sessionStore.isAnonymous && sessionStore.user.username == user.value?.username;
|
||||||
});
|
});
|
||||||
|
|
||||||
const meterValue = ref([
|
const meterValue = ref([
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import Button from 'primevue/button';
|
||||||
import Panel from 'primevue/panel';
|
import Panel from 'primevue/panel';
|
||||||
import Sticker from "@/components/Sticker.vue";
|
import Sticker from "@/components/Sticker.vue";
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useUserStore } from "@/stores/userStore";
|
import { useSessionStore } from "@/stores/sessionStore";
|
||||||
import { useStickerStore } from "@/stores/stickerStore";
|
import { useStickerStore } from "@/stores/stickerStore";
|
||||||
|
|
||||||
|
const sessionStore = useSessionStore();
|
||||||
const stickerStore = useStickerStore();
|
const stickerStore = useStickerStore();
|
||||||
const userStore = useUserStore();
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const uuid = ref<string>(route.params.uuid as string);
|
const uuid = ref<string>(route.params.uuid as string);
|
||||||
|
|
@ -28,7 +28,7 @@ const second = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
function claimSticker() {
|
function claimSticker() {
|
||||||
stickerStore.setOwner(userStore.user);
|
stickerStore.setOwner(sessionStore.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -56,12 +56,12 @@ function claimSticker() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
v-bind:disabled="userStore.isAnonymous"
|
v-bind:disabled="sessionStore.isAnonymous"
|
||||||
v-if="stickerStore.sticker?.owner == null"
|
v-if="stickerStore.sticker?.owner == null"
|
||||||
v-on:click="claimSticker">
|
v-on:click="claimSticker">
|
||||||
This is my sticker!
|
This is my sticker!
|
||||||
</Button>
|
</Button>
|
||||||
<span v-if="userStore.isAnonymous">
|
<span v-if="sessionStore.isAnonymous">
|
||||||
Log in to claim your sticker.
|
Log in to claim your sticker.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue