progress on player list

This commit is contained in:
Sascha Kühl 2025-05-27 08:15:03 +02:00
parent a7b784de27
commit 3fa9ff42b5
10 changed files with 61 additions and 35 deletions

View File

@ -1,7 +1,7 @@
import { createRouter, createWebHistory } from '@ionic/vue-router'; import { createRouter, createWebHistory } from '@ionic/vue-router';
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { RouteRecordRaw } from 'vue-router'; import { RouteRecordRaw } from 'vue-router';
import PitcherList from '../views/PitcherList.vue' import PlayerList from '../views/PlayerList.vue'
import LoginView from '../views/LoginView.vue' import LoginView from '../views/LoginView.vue'
import HomeView from '../views/HomeView.vue' import HomeView from '../views/HomeView.vue'
import BullpenView from "@/views/BullpenView.vue"; import BullpenView from "@/views/BullpenView.vue";
@ -17,7 +17,7 @@ const routes: Array<RouteRecordRaw> = [
{ path: '/setup', component: SetupView }, { path: '/setup', component: SetupView },
{ path: '/home', component: HomeView }, { path: '/home', component: HomeView },
{ path: '/profile', component: ProfileView }, { path: '/profile', component: ProfileView },
{ path: '/pitchers', component: PitcherList }, { path: '/player', component: PlayerList },
{ path: '/bullpen', component: BullpenView }, { path: '/bullpen', component: BullpenView },
{ path: '/stats', component: BullpenListView }, { path: '/stats', component: BullpenListView },
{ path: '/summary', component: BullpenSummaryView } { path: '/summary', component: BullpenSummaryView }

View File

@ -28,6 +28,23 @@ class TokenService {
removeUser() { removeUser() {
localStorage.removeItem("auth"); localStorage.removeItem("auth");
} }
isAdmin() {
return this.hasRole('ROLE_ADMIN');
}
isCoach() {
return this.hasRole('ROLE_COACH');
}
isPlayer() {
return this.hasRole('ROLE_PLAYER');
}
private hasRole(role: string) {
const user = this.getUser();
return user?.roles ? user.roles.includes(role) : false;
}
} }
export default new TokenService(); export default new TokenService();

View File

@ -5,9 +5,6 @@ import {ActionContext, Module} from 'vuex';
import {RootState} from './index'; import {RootState} from './index';
import TokenService from "@/services/TokenService"; import TokenService from "@/services/TokenService";
import UserService from "@/services/UserService"; import UserService from "@/services/UserService";
import PlayerService from "@/services/PlayerService";
import UserInfo from '@/types/UserInfo';
import Player from '@/types/Player';
export interface AuthState { export interface AuthState {
isAuthenticated: boolean; isAuthenticated: boolean;

View File

@ -18,13 +18,13 @@ const pitchTypes: Module<PlayerState, RootState> = {
determinePlayer({commit}: PlayerActionContext, user: User) { determinePlayer({commit}: PlayerActionContext, user: User) {
if (user.roles.includes('ROLE_PLAYER')) { if (user.roles.includes('ROLE_PLAYER')) {
playerService.fetchByUserId(user.id).then(player => { playerService.fetchByUserId(user.id).then(player => {
commit('initialize', player); commit('select', player);
}); });
} }
} }
}, },
mutations: { mutations: {
initialize(state, player: Player) { select(state, player: Player) {
state.player = player; state.player = player;
} }
} }

View File

@ -1,3 +1,5 @@
import User from "@/types/User";
export default interface Player { export default interface Player {
id: number, id: number,
gender: string, gender: string,
@ -9,5 +11,5 @@ export default interface Player {
state: string, state: string,
createdAt: Date, createdAt: Date,
updatedAt: Date, updatedAt: Date,
userId: number user: User
} }

View File

@ -1,28 +1,32 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed, ref} from 'vue'; import {computed, ref} from 'vue';
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonAvatar, IonButton, IonIcon } from '@ionic/vue'; import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonAvatar, IonButton, IonIcon } from '@ionic/vue';
import { playOutline, statsChartOutline, personOutline, logOutOutline } from 'ionicons/icons'; import { playOutline, statsChartOutline, personOutline, logOutOutline, personAddOutline } from 'ionicons/icons';
// import userImage from '../assets/groot.jpg'
import {useStore} from "vuex"; import {useStore} from "vuex";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import BullpenSessionService from "@/services/BullpenSessionService"; import BullpenSessionService from "@/services/BullpenSessionService";
import TokenService from "@/services/TokenService";
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
const userImage = ref(null); const userImage = ref(null);
// const userImage = ref('../assets/groot.jpg');
const pitcher = computed(() => store.state.auth.user); const user = computed(() => store.state.auth.user);
const player = computed(() => store.state.player.player);
const isAuthenticated = computed(() => store.state.auth.isAuthenticated); const isAuthenticated = computed(() => store.state.auth.isAuthenticated);
if (pitcher.value === undefined || pitcher.value === null || pitcher.value === '') { if (user.value === undefined || user.value === null || user.value === '') {
router.push({ path: '/login' }); router.push({ path: '/login' });
} }
const startBullpen = () => { const startBullpen = () => {
store.dispatch("bullpen/start", pitcher.value); if (player.value === undefined || player.value === null || player.value === '') {
router.push({ path: '/player' });
} else {
store.dispatch("bullpen/start", user.value);
router.push({ path: '/bullpen' }); router.push({ path: '/bullpen' });
}
}; };
const showStats = () => { const showStats = () => {
@ -43,13 +47,16 @@ const logout = () => {
console.log(error); console.log(error);
}); });
} }
const addPlayer = () => {}
</script> </script>
<template> <template>
<ion-page> <ion-page>
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title v-if="isAuthenticated">Home of {{ pitcher.firstName }} {{ pitcher.lastName }}</ion-title> <ion-title v-if="isAuthenticated">Home of {{ user.firstName }} {{ user.lastName }}</ion-title>
<ion-title v-else>Home</ion-title> <ion-title v-else>Home</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@ -64,7 +71,7 @@ const logout = () => {
<ion-icon :icon="personOutline" class="avatar-placeholder" /> <ion-icon :icon="personOutline" class="avatar-placeholder" />
</template> </template>
</ion-avatar> </ion-avatar>
<div v-if="isAuthenticated" class="user-name">{{ pitcher.firstName }} {{ pitcher.lastName }}</div> <div v-if="isAuthenticated" class="user-name">{{ user.firstName }} {{ user.lastName }}</div>
</div> </div>
<div class="button-grid"> <div class="button-grid">
@ -84,6 +91,10 @@ const logout = () => {
<ion-icon :icon="logOutOutline" slot="start" /> <ion-icon :icon="logOutOutline" slot="start" />
Logout Logout
</ion-button> </ion-button>
<ion-button v-if="TokenService.isCoach()" @click="addPlayer" class="grid-button">
<ion-icon :icon="personAddOutline" slot="start" />
Add Player
</ion-button>
</div> </div>
</ion-content> </ion-content>
</ion-page> </ion-page>

View File

@ -1,24 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useStore } from 'vuex'
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonList, IonItem, IonLabel } from '@ionic/vue'; import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonList, IonItem, IonLabel } from '@ionic/vue';
import UserService from "@/services/UserService"; import PlayerService from "@/services/PlayerService";
import User from "@/types/User"; import Player from "@/types/Player";
// import BullpenSessionService from "@/services/BullpenSessionService";
const pitchers = ref<User[]>([]); const players = ref<Player[]>([]);
const router = useRouter(); const router = useRouter();
// const bps = ref(BullpenSessionService); const store = useStore();
// bps.value.clear();
onMounted(async () => { onMounted(async () => {
pitchers.value = await UserService.fetchAll(); players.value = await PlayerService.fetchAll();
}); });
const goToPreparePitch = (pitcher: User) => { const selectPlayer = (player: Player) => {
console.log(pitcher); console.log(player);
// bps.value.startSession( pitcher ); store.commit("player/select", player);
router.push({ path: '/bullpen' }); router.push({ path: '/bullpen' });
}; };
@ -40,8 +38,8 @@ const goToPreparePitch = (pitcher: User) => {
</ion-header> </ion-header>
<ion-list> <ion-list>
<ion-item v-for="(pitcher, index) in pitchers" :key="index" button @click="goToPreparePitch(pitcher)"> <ion-item v-for="(player, index) in players" :key="index" button @click="selectPlayer(player)">
<ion-label>{{ pitcher.firstName }} {{ pitcher.lastName }}</ion-label> <ion-label>{{ player.user.firstName }} {{ player.user.lastName }}</ion-label>
</ion-item> </ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>

View File

@ -1,10 +1,10 @@
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import HomePage from '../../src/views/PitcherList.vue' import PlayerList from '../../src/views/PlayerList.vue'
import { describe, expect, test } from 'vitest' import { describe, expect, test } from 'vitest'
describe('PitcherList.vue', () => { describe('PlayerList.vue', () => {
test('renders home vue', () => { test('renders home vue', () => {
const wrapper = mount(HomePage) const wrapper = mount(PlayerList)
expect(wrapper.text()).toMatch('Ready to create an app?') expect(wrapper.text()).toMatch('Ready to create an app?')
}) })
}) })

View File

@ -34,7 +34,7 @@ exports.findAll = (req, res) => {
Player.findAll({ Player.findAll({
where: condition, where: condition,
include: { model: User } include: ['user']
}).then(data => { }).then(data => {
res.send(data); res.send(data);
}).catch(err => { }).catch(err => {

View File

@ -9,7 +9,8 @@ module.exports = (sequelize, DataTypes) => {
*/ */
static associate(models) { static associate(models) {
Player.belongsTo(models.User, { Player.belongsTo(models.User, {
foreignKey: "userId" foreignKey: "userId",
as: "user"
}); });
} }
} }