Compare commits
2 Commits
09cb9dff14
...
acfaffad2c
| Author | SHA1 | Date |
|---|---|---|
|
|
acfaffad2c | |
|
|
66b41022b4 |
|
|
@ -49,7 +49,8 @@ onMounted(() => {
|
||||||
if (isOnline.value && !isAuthenticated.value) {
|
if (isOnline.value && !isAuthenticated.value) {
|
||||||
router.push({path: '/login'});
|
router.push({path: '/login'});
|
||||||
} else {
|
} else {
|
||||||
// checkStoredUserData();
|
store.dispatch('pitchTypes/fetch');
|
||||||
|
store.dispatch("player/selectPlayer", user.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -86,7 +87,7 @@ const logoutUser = () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ion-app>
|
<ion-app>
|
||||||
<ion-menu content-id="user-menu">
|
<ion-menu v-if="isAuthenticated" content-id="user-menu">
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="secondary">
|
<ion-buttons slot="secondary">
|
||||||
|
|
@ -118,7 +119,7 @@ const logoutUser = () => {
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ion-menu>
|
</ion-menu>
|
||||||
<ion-router-outlet />
|
<ion-router-outlet id="user-menu"/>
|
||||||
</ion-app>
|
</ion-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const user = computed(() => store.state.auth.user);
|
||||||
|
|
||||||
|
const managePlayers = () => {
|
||||||
|
router.push({ path: "/players" });
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<p>Willkommen, Coach {{ user.firstName }}!</p>
|
||||||
|
<ion-button @click="managePlayers">Spieler verwalten</ion-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {computed, reactive, ref} from "vue";
|
||||||
|
import {
|
||||||
|
InfiniteScrollCustomEvent,
|
||||||
|
IonIcon,
|
||||||
|
IonInfiniteScroll,
|
||||||
|
IonInfiniteScrollContent,
|
||||||
|
IonItem,
|
||||||
|
IonLabel,
|
||||||
|
IonList
|
||||||
|
} from '@ionic/vue';
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useStore } from "vuex";
|
||||||
|
import {baseballOutline} from 'ionicons/icons';
|
||||||
|
import Bullpen from '@/types/Bullpen';
|
||||||
|
import BullpenSessionService from "@/services/BullpenSessionService";
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import PitchType from '@/types/PitchType';
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const user = computed(() => store.state.auth.user);
|
||||||
|
const pitchTypes = computed(() => store.state.pitchTypes.pitchTypes);
|
||||||
|
|
||||||
|
const items = reactive<Bullpen[]>([]);
|
||||||
|
const page = ref(0);
|
||||||
|
|
||||||
|
const startBullpenSession = () => {
|
||||||
|
router.push({ path: "/bullpen" });
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateItems = () => {
|
||||||
|
BullpenSessionService
|
||||||
|
.fetchAllByUser(user.value.id, page.value, 10)
|
||||||
|
.then((bullpens) => {
|
||||||
|
++page.value;
|
||||||
|
bullpens.data.forEach((bullpen: Bullpen) => {
|
||||||
|
items.push(bullpen);
|
||||||
|
})
|
||||||
|
}, error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (date: Date) => {
|
||||||
|
return dayjs(date).format('YYYY.MM.DD HH:mm');
|
||||||
|
}
|
||||||
|
|
||||||
|
const determinePitchTypeName = (id: number): string => {
|
||||||
|
const pitchType = pitchTypes.value.find((pitchType: PitchType) => pitchType.id === id);
|
||||||
|
|
||||||
|
return pitchType?.name ?? 'Unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
const ionInfinite = (event: InfiniteScrollCustomEvent) => {
|
||||||
|
generateItems();
|
||||||
|
setTimeout(() => event.target.complete(), 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
generateItems();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ion-list>
|
||||||
|
<ion-item v-for="(bullpen, index) in items" :key="index" lines="none" class="custom-item" :button="true" detail="false">
|
||||||
|
<!-- Top-left icon -->
|
||||||
|
<ion-icon :icon="baseballOutline" slot="start" class="item-icon"></ion-icon>
|
||||||
|
|
||||||
|
<ion-label class="item-labels">
|
||||||
|
<!-- First Progress Bar -->
|
||||||
|
<div class="progress-section">
|
||||||
|
<div class="top-row">
|
||||||
|
<span class="left-label">Task 1</span>
|
||||||
|
<span class="right-label">{{ (0.57 * 100).toFixed(0) }}%</span>
|
||||||
|
</div>
|
||||||
|
<ion-progress-bar :value="0.57"></ion-progress-bar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Second Progress Bar -->
|
||||||
|
<div class="progress-section">
|
||||||
|
<div class="top-row">
|
||||||
|
<span class="left-label">Task 2</span>
|
||||||
|
<span class="right-label">{{ (0.33 * 100).toFixed(0) }}%</span>
|
||||||
|
</div>
|
||||||
|
<ion-progress-bar :value="0.33" color="secondary"></ion-progress-bar>
|
||||||
|
</div>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- <ion-item v-for="(bullpen, index) in items" :key="index">-->
|
||||||
|
<!-- <ion-icon aria-hidden="true" :icon="baseball" slot="start"></ion-icon>-->
|
||||||
|
<!-- <ion-label>Bullpen from ({{formatDate(bullpen.startedAt)}})</ion-label>-->
|
||||||
|
<!-- <ion-list v-for="(pitch, index) in bullpen.pitches" :key="index">-->
|
||||||
|
<!-- <ion-item>-->
|
||||||
|
<!-- <ion-icon slot="start" :icon="baseballOutline" class="icon-login"></ion-icon>-->
|
||||||
|
<!-- <ion-label>{{determinePitchTypeName(pitch.pitchTypeId)}}</ion-label>-->
|
||||||
|
<!-- <ion-badge>{{pitch.aimedArea}}</ion-badge>-->
|
||||||
|
<!-- <ion-badge>{{pitch.hitArea}}</ion-badge>-->
|
||||||
|
<!-- </ion-item>-->
|
||||||
|
<!-- </ion-list>-->
|
||||||
|
<!-- </ion-item>-->
|
||||||
|
</ion-list>
|
||||||
|
<ion-infinite-scroll @ionInfinite="ionInfinite">
|
||||||
|
<ion-infinite-scroll-content></ion-infinite-scroll-content>
|
||||||
|
</ion-infinite-scroll>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.custom-item {
|
||||||
|
align-items: flex-start !important; /* important override */
|
||||||
|
--padding-start: 16px;
|
||||||
|
--inner-padding-end: 16px;
|
||||||
|
--min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: var(--ion-color-danger);
|
||||||
|
margin-right: 12px;
|
||||||
|
margin-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-labels {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-section {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-label {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,44 +1,32 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, reactive} from 'vue';
|
import {computed} from 'vue';
|
||||||
import {
|
import {
|
||||||
IonPage,
|
IonPage,
|
||||||
IonHeader,
|
IonHeader,
|
||||||
IonToolbar,
|
IonToolbar,
|
||||||
IonTitle,
|
IonTitle,
|
||||||
IonContent,
|
IonContent,
|
||||||
IonAvatar,
|
|
||||||
IonButtons,
|
IonButtons,
|
||||||
IonIcon,
|
IonIcon,
|
||||||
IonMenuButton,
|
IonMenuButton,
|
||||||
IonFab,
|
IonFab,
|
||||||
IonFabButton,
|
IonFabButton,
|
||||||
IonInfiniteScroll,
|
|
||||||
IonInfiniteScrollContent,
|
|
||||||
InfiniteScrollCustomEvent,
|
|
||||||
IonList,
|
|
||||||
IonItem,
|
|
||||||
IonLabel, IonBadge,
|
|
||||||
} from '@ionic/vue';
|
} from '@ionic/vue';
|
||||||
import {
|
import {
|
||||||
baseball,
|
|
||||||
add,
|
add,
|
||||||
baseballOutline
|
|
||||||
} from 'ionicons/icons';
|
} from 'ionicons/icons';
|
||||||
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";
|
import TokenService from "@/services/TokenService";
|
||||||
import dayjs from "dayjs";
|
|
||||||
import Bullpen from "@/types/Bullpen";
|
|
||||||
import PitchType from "@/types/PitchType";
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
|
||||||
const user = computed(() => store.state.auth.user);
|
const user = computed(() => store.state.auth.user);
|
||||||
const pitchTypes = computed(() => store.state.pitchTypes.pitchTypes);
|
|
||||||
|
|
||||||
const isAuthenticated = computed(() => store.state.auth.isAuthenticated);
|
import PlayerContent from "@/components/PlayerComponent.vue"
|
||||||
|
import CoachContent from "@/components/CoachComponent.vue";
|
||||||
|
|
||||||
if (user.value === undefined || user.value === null || user.value === '') {
|
if (user.value === undefined || user.value === null || user.value === '') {
|
||||||
router.push({ path: '/login' });
|
router.push({ path: '/login' });
|
||||||
|
|
@ -66,43 +54,12 @@ const addPlayer = () => {
|
||||||
router.push({ path: '/player/create' });
|
router.push({ path: '/player/create' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = reactive<Bullpen[]>([]);
|
|
||||||
const page = ref(0);
|
|
||||||
|
|
||||||
const generateItems = () => {
|
|
||||||
BullpenSessionService
|
|
||||||
.fetchAllByUser(user.value.id, page.value, 10)
|
|
||||||
.then((bullpens) => {
|
|
||||||
++page.value;
|
|
||||||
bullpens.data.forEach((bullpen: Bullpen) => {
|
|
||||||
items.push(bullpen);
|
|
||||||
})
|
|
||||||
}, error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatDate = (date: Date) => {
|
|
||||||
return dayjs(date).format('YYYY.MM.DD HH:mm');
|
|
||||||
}
|
|
||||||
|
|
||||||
const determinePitchTypeName = (id: number): string => {
|
|
||||||
const pitchType = pitchTypes.value.find((pitchType: PitchType) => pitchType.id === id);
|
|
||||||
|
|
||||||
return pitchType?.name ?? 'Unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
const ionInfinite = (event: InfiniteScrollCustomEvent) => {
|
|
||||||
generateItems();
|
|
||||||
setTimeout(() => event.target.complete(), 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
generateItems();
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ion-page id="user-menu">
|
<ion-page>
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-buttons slot="start">
|
<ion-buttons slot="start">
|
||||||
|
|
@ -115,23 +72,8 @@ generateItems();
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list>
|
<PlayerContent v-if="TokenService.isPlayer()" />
|
||||||
<ion-item v-for="(bullpen, index) in items" :key="index">
|
<CoachContent v-else-if="TokenService.isCoach()" />
|
||||||
<ion-icon aria-hidden="true" :icon="baseball" slot="start"></ion-icon>
|
|
||||||
<ion-label>Bullpen from ({{formatDate(bullpen.startedAt)}})</ion-label>
|
|
||||||
<ion-list v-for="(pitch, index) in bullpen.pitches" :key="index">
|
|
||||||
<ion-item>
|
|
||||||
<ion-icon slot="start" :icon="baseballOutline" class="icon-login"></ion-icon>
|
|
||||||
<ion-label>{{determinePitchTypeName(pitch.pitchTypeId)}}</ion-label>
|
|
||||||
<ion-badge>{{pitch.aimedArea}}</ion-badge>
|
|
||||||
<ion-badge>{{pitch.hitArea}}</ion-badge>
|
|
||||||
</ion-item>
|
|
||||||
</ion-list>
|
|
||||||
</ion-item>
|
|
||||||
</ion-list>
|
|
||||||
<ion-infinite-scroll @ionInfinite="ionInfinite">
|
|
||||||
<ion-infinite-scroll-content></ion-infinite-scroll-content>
|
|
||||||
</ion-infinite-scroll>
|
|
||||||
<!-- <div class="user-container">-->
|
<!-- <div class="user-container">-->
|
||||||
<!-- <ion-avatar class="user-avatar">-->
|
<!-- <ion-avatar class="user-avatar">-->
|
||||||
<!-- <template v-if="userImage">-->
|
<!-- <template v-if="userImage">-->
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ const submit = handleSubmit((values, { resetForm }) => {
|
||||||
return store.dispatch('pitchTypes/fetch');
|
return store.dispatch('pitchTypes/fetch');
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
resetForm();
|
resetForm();
|
||||||
router.push({path: '/home'});
|
return router.push({path: '/home'});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
services:
|
services:
|
||||||
postgres:
|
dev-db:
|
||||||
image: postgres:14-alpine
|
image: postgres:15
|
||||||
container_name: postgres14
|
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5434:5432"
|
||||||
volumes:
|
|
||||||
- ~/apps/postgres:/var/lib/postgresql/data
|
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_DB: bullpen-dev
|
POSTGRES_DB: bullpen-dev
|
||||||
|
volumes:
|
||||||
|
- /tmp/test-pgdata:/var/lib/postgresql/data
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue