Compare commits

..

No commits in common. "98cd757666b339499c44b8c4170af61b27836833" and "ccc3ffe7713cd9bc83614f665ffc5d44cd6b81f9" have entirely different histories.

11 changed files with 265 additions and 388 deletions

View File

@ -19,7 +19,7 @@ const routes: Array<RouteRecordRaw> = [
{ path: '/home', component: HomeView }, { path: '/home', component: HomeView },
{ path: '/profile', component: ProfileView }, { path: '/profile', component: ProfileView },
{ path: '/players', component: PlayerList }, { path: '/players', component: PlayerList },
{ path: '/profile/:id', component: ProfileView }, // { path: '/player', component: PlayerView },
{ 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

@ -9,33 +9,6 @@ class PlayerService extends ApiService<Player> {
super('players'); super('players');
} }
public emptyPlayer(): Player {
return {
id: 0,
gender: 'male',
bats: 'right',
throws: 'right',
height: 187,
weight: 84,
state: 'active',
jerseyNumber: 23,
createdAt: new Date(),
updatedAt: new Date(),
user: {
id: 0,
auth: {
email: 'test@de.de',
password: 'test$123'
},
firstName: 'Demo',
lastName: 'Player',
dateOfBirth: new Date(),
roles: ['player'],
createdAt: new Date(),
updatedAt: new Date()
}
};
}
public fetchByUserId(userId: number): Promise<Player> { public fetchByUserId(userId: number): Promise<Player> {
return api return api
.get(`/${this.name}/user/${userId}`, { headers: authHeader() }) .get(`/${this.name}/user/${userId}`, { headers: authHeader() })

View File

@ -1,13 +1,11 @@
export default interface User { export default interface User {
id: number, id: number,
email: string,
firstName: string, firstName: string,
lastName: string, lastName: string,
dateOfBirth: Date, dateOfBirth: Date,
roles: string[], roles: string[],
createdAt: Date, createdAt: Date,
updatedAt: Date, updatedAt: Date,
auth: { auth: { email: string }
email: string,
password: string
}
} }

View File

@ -2,21 +2,14 @@
import { import {
IonButton, IonButton,
IonCard, IonCard,
IonCardHeader,
IonCardTitle, IonCardTitle,
IonCardSubtitle, IonCardSubtitle,
IonCardContent,
IonContent, IonContent,
IonFooter, IonFooter,
IonHeader, IonHeader,
IonPage, IonPage,
IonTitle, IonTitle,
IonToolbar, IonToolbar, IonLabel, IonList, IonItem, IonIcon, IonBadge
IonLabel,
IonList,
IonItem,
IonIcon,
IonBadge
} from "@ionic/vue"; } from "@ionic/vue";
import { import {
baseballOutline baseballOutline

View File

@ -26,7 +26,7 @@ const router = useRouter();
const store = useStore(); const store = useStore();
const isAuthenticated = computed(() => store.state.auth.isAuthenticated); const isAuthenticated = computed(() => store.state.auth.isAuthenticated);
const player = computed(() => store.state.player.player); const pitcher = computed(() => store.state.auth.user);
const pitchTypes = computed(() => store.state.pitchTypes.pitchTypes); const pitchTypes = computed(() => store.state.pitchTypes.pitchTypes);
const bullpen = computed(() => store.state.bullpen); const bullpen = computed(() => store.state.bullpen);
@ -52,7 +52,7 @@ const gotoHome = () => {
<ion-page> <ion-page>
<ion-header :translucent="true"> <ion-header :translucent="true">
<ion-toolbar> <ion-toolbar>
<ion-title v-if="isAuthenticated">Bullpen Summary {{ player.firstName }} {{ player.lastName }}</ion-title> <ion-title v-if="isAuthenticated">Bullpen Summary {{ pitcher.firstName }} {{ pitcher.lastName }}</ion-title>
<ion-title v-else>Bullpen Summary</ion-title> <ion-title v-else>Bullpen Summary</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>

View File

@ -1,14 +1,7 @@
<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 { import { playOutline, statsChartOutline, personOutline, logOutOutline, personAddOutline } from 'ionicons/icons';
playOutline,
statsChartOutline,
personOutline,
logOutOutline,
personAddOutline,
ellipsisHorizontal, ellipsisVertical
} 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";
@ -28,7 +21,7 @@ if (user.value === undefined || user.value === null || user.value === '') {
const startBullpen = () => { const startBullpen = () => {
if (TokenService.isPlayer()) { if (TokenService.isPlayer()) {
store.dispatch('player/selectPlayer', user.value).then(() => { store.dispatch('player/selectPlayer', user).then(() => {
store.dispatch("bullpen/start", user.value); store.dispatch("bullpen/start", user.value);
router.push({ path: '/bullpen' }); router.push({ path: '/bullpen' });
}); });
@ -45,7 +38,7 @@ const showStats = () => {
}; };
const showProfile = () => { const showProfile = () => {
router.push({ path: `/profile/${user.value.id}`}); router.push({ path: `/player/view/${user.value.id}`});
}; };
const logout = () => { const logout = () => {
@ -68,19 +61,6 @@ const addPlayer = () => {
<ion-toolbar> <ion-toolbar>
<ion-title v-if="isAuthenticated">Home of {{ user.firstName }} {{ user.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-buttons slot="primary">-->
<!-- <ion-button id="user-menu-trigger">-->
<!-- <ion-icon slot="icon-only" :ios="ellipsisHorizontal" :md="ellipsisVertical"></ion-icon>-->
<!-- </ion-button>-->
<!-- <ion-popover trigger="user-menu-trigger" trigger-action="click">-->
<!-- <ion-content class="ion-padding">-->
<!-- <ion-list>-->
<!-- <ion-item button @click="showProfile">Profile</ion-item>-->
<!-- <ion-item button @click="logout">Logout</ion-item>-->
<!-- </ion-list>-->
<!-- </ion-content>-->
<!-- </ion-popover>-->
<!-- </ion-buttons>-->
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
@ -102,7 +82,7 @@ const addPlayer = () => {
<ion-icon :icon="playOutline" slot="start" /> <ion-icon :icon="playOutline" slot="start" />
Start Bullpen Session Start Bullpen Session
</ion-button> </ion-button>
<ion-button v-if="TokenService.isPlayer()" @click="showStats" class="grid-button"> <ion-button @click="showStats" class="grid-button">
<ion-icon :icon="statsChartOutline" slot="start" /> <ion-icon :icon="statsChartOutline" slot="start" />
Show Bullpen Stats Show Bullpen Stats
</ion-button> </ion-button>

View File

@ -9,7 +9,6 @@ import {
IonCardHeader, IonCardHeader,
IonCardTitle, IonCardTitle,
IonCardContent, IonCardContent,
IonInputPasswordToggle,
} from "@ionic/vue"; } from "@ionic/vue";
import {Field, useForm} from 'vee-validate'; import {Field, useForm} from 'vee-validate';
@ -133,7 +132,6 @@ const changeServer = () => {
id="password" id="password"
name="password" name="password"
type="password"> type="password">
<ion-input-password-toggle slot="end"></ion-input-password-toggle>
</ion-input> </ion-input>
</Field> </Field>
</ion-item> </ion-item>

View File

@ -2,8 +2,7 @@
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 { useStore } from 'vuex'
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonList, IonItem, IonLabel, IonIcon, IonText } from '@ionic/vue'; import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonList, IonItem, IonLabel } from '@ionic/vue';
import {personCircle} from "ionicons/icons";
import PlayerService from "@/services/PlayerService"; import PlayerService from "@/services/PlayerService";
import Player from "@/types/Player"; import Player from "@/types/Player";
@ -28,24 +27,20 @@ const selectPlayer = (player: Player) => {
<ion-page> <ion-page>
<ion-header :translucent="true"> <ion-header :translucent="true">
<ion-toolbar> <ion-toolbar>
<ion-title>Players</ion-title> <ion-title>Pitchers</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content :fullscreen="true"> <ion-content :fullscreen="true">
<ion-header collapse="condense"> <ion-header collapse="condense">
<ion-toolbar> <ion-toolbar>
<ion-title size="large">Player List</ion-title> <ion-title size="large">Pitchers</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-list> <ion-list>
<ion-item v-for="(player, index) in players" :key="index" button @click="selectPlayer(player)"> <ion-item v-for="(player, index) in players" :key="index" button @click="selectPlayer(player)">
<ion-icon aria-hidden="true" :icon="personCircle" slot="start"></ion-icon> <ion-label>{{ player.user.firstName }} {{ player.user.lastName }}</ion-label>
<ion-label>
<strong>{{ player.user.firstName }} {{ player.user.lastName }} <ion-badge slot="start">{{ player.jerseyNumber}}</ion-badge></strong>
<ion-text>Bats: {{player.bats}} / Throws: {{player.throws}}</ion-text>
</ion-label>
</ion-item> </ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>
@ -53,16 +48,6 @@ const selectPlayer = (player: Player) => {
</template> </template>
<style scoped> <style scoped>
ion-label strong {
display: block;
max-width: calc(100% - 60px);
overflow: hidden;
text-overflow: ellipsis;
}
#container { #container {
text-align: center; text-align: center;

View File

@ -5,16 +5,15 @@ import {
IonToolbar, IonToolbar,
IonTitle, IonTitle,
IonContent, IonContent,
IonGrid,
IonRow,
IonCol,
IonItem, IonItem,
IonInput, IonInput,
IonIcon,
IonButton, IonButton,
IonCard,
IonCardHeader,
IonCardTitle,
IonCardContent,
IonSelect, IonSelect,
IonSelectOption, IonSelectOption
IonInputPasswordToggle,
} from '@ionic/vue'; } from '@ionic/vue';
import { Field, useForm } from 'vee-validate'; import { Field, useForm } from 'vee-validate';
import * as yup from 'yup'; import * as yup from 'yup';
@ -24,10 +23,37 @@ import Player from '@/types/Player';
// import CrudField from '@/components/CrudField.vue' // import CrudField from '@/components/CrudField.vue'
import PlayerService from '@/services/PlayerService'; import PlayerService from '@/services/PlayerService';
import {useRoute, useRouter} from 'vue-router'; import {useRoute, useRouter} from 'vue-router';
import {save, stop} from "ionicons/icons";
const props = defineProps<{ player?: Player }>();
const defaultPlayer: Player = {
id: 0,
gender: 'male',
bats: 'right',
throws: 'right',
height: 0,
weight: 0,
state: 'active',
jerseyNumber: 0,
createdAt: new Date(),
updatedAt: new Date(),
user: {
id: 0,
email: '',
firstName: '',
lastName: '',
dateOfBirth: new Date(),
roles: [],
createdAt: new Date(),
updatedAt: new Date(),
auth: {
email: ''
}
}
}
// Computed reactive player object: Either use the provided player or initialize with default // Computed reactive player object: Either use the provided player or initialize with default
const player = ref<Player>( PlayerService.emptyPlayer() ); const player = ref<Player>(props.player ? { ...props.player } : { ...defaultPlayer });
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
@ -42,32 +68,24 @@ const mode = computed(() => {
const formattedDate = ref(player.value.user.dateOfBirth.toISOString().split('T')[0]); const formattedDate = ref(player.value.user.dateOfBirth.toISOString().split('T')[0]);
const schema = yup.object({ const schema = yup.object({
user: yup.object({ email: yup
auth: yup.object({ .string()
email: yup.string().email('Invalid email address').required('E-Mail is required'), .email('Invalid email address')
password: yup.string() .required('E-Mail is required'),
.min(8, 'Minimum 8 characters') firstName: yup.string().required('First name is required'),
.matches(/\d/, 'Must include a number') lastName: yup.string().required('Last name is required'),
.matches(/[^A-Za-z\d]/, 'Must include a special character') dateOfBirth: yup
.required('Password is required') .date()
}), .max(dayjs().subtract(5, 'year').toDate(), 'Player must be at least 5 years old')
firstName: yup.string().required('First name is required'), .required('Geburtsdatum ist erforderlich'),
lastName: yup.string().required('Last name is required'),
dateOfBirth: yup
.date()
.max(dayjs()
.subtract(5, 'year')
.toDate(), 'Player must be at least 5 years old')
.required('Date of birth is required'),
}),
gender: yup.string().required('Gender is required'), gender: yup.string().required('Gender is required'),
bats: yup bats: yup
.string() .string()
.oneOf(['right', 'left', 'both'], 'Invalid selection') .oneOf(['R', 'L', 'S'], 'Invalid selection')
.required('Batting hand is required'), .required('Batting hand is required'),
throws: yup throws: yup
.string() .string()
.oneOf(['right', 'left'], 'Invalid selection') .oneOf(['R', 'L'], 'Invalid selection')
.required('Throwing hand is required'), .required('Throwing hand is required'),
jerseyNumber: yup jerseyNumber: yup
.number() .number()
@ -87,47 +105,67 @@ const schema = yup.object({
.required('Height is required'), .required('Height is required'),
}); });
const { errors, resetForm, handleSubmit, defineField, setFieldValue } = useForm({ const { errors, resetForm, handleSubmit, defineField } = useForm({
validationSchema: schema, validationSchema: schema,
initialValues: player.value initialValues: player.value
}); });
// Watch for changes in props.player to reset form when editing
// watch(
// () => route.params.id || route.query.id,
// (newId) => {
// if (newId) {
// fetchPlayerById(Number(newId)); // Fetch player when the ID changes
// }
// }
// );
onMounted(() => { onMounted(() => {
if (mode.value === 'view' || mode.value === 'edit') { if (mode.value === 'view' || mode.value === 'edit') {
PlayerService PlayerService.fetchById(Number(id))
.fetchById(Number(id))
.then((response) => { .then((response) => {
player.value = response; player.value = response;
resetForm({ values: { ...player.value } }); // Reset form with fetched data
formattedDate.value = dayjs(player.value.user.dateOfBirth).format('YYYY-MM-DD');
}) })
.catch((error) => { .catch((error) => {
console.error('Failed to fetch player:', error); console.error('Failed to fetch player:', error);
}); });
} else {
console.log('Creating new player');
resetForm({values: {...player.value}}); // Reset form with fetched data
formattedDate.value = dayjs(player.value.user.dateOfBirth).format('YYYY-MM-DD');
} }
resetForm({ values: { ...player.value } }); // Reset form with fetched data
formattedDate.value = dayjs(player.value.user.dateOfBirth).format('YYYY-MM-DD');
}); });
const submit = handleSubmit((values) => { // const fetchPlayerById = async (id: number) => {
// try {
// const data = await PlayerService.fetchByUserId(id); // Fetch the player from the API
// player.value = { ...data }; // Load the API response into the form
// resetForm({ values: { ...player.value } }); // Reset form with fetched data
// formattedDate.value = dayjs(player.value.user.dateOfBirth).format('YYYY-MM-DD');
// isEdit.value = true; // Set to edit mode
// } catch (error) {
// console.error('Error fetching player data:', error);
// }
// };
// Submit logic: Differentiate between create and update
const submit = handleSubmit((values: Player) => {
if (mode.value === 'edit') { if (mode.value === 'edit') {
console.log('Updating player:', values); console.log('Updating player:', values); // Replace with update logic
// PlayerService.(player.value.id, player.value).then(() => router.push('/players')); // PlayerService.(player.value.id, player.value).then(() => router.push('/players'));
} else if (mode.value === 'create') { } else if (mode.value === 'create') {
console.log('Creating player:', values); console.log('Creating player:', values); // Replace with create logic
PlayerService.save(values).then(() => router.push('/home')); PlayerService.save(player.value).then(() => router.push('/home'));
} }
}, ({errors}) => {
console.log(errors);
}); });
const onDateChange = (value: string) => {
formattedDate.value = value; // Update formatted string
player.value.user.dateOfBirth = new Date(value); // Convert to Date object and update
};
const [email, emailAttrs] = defineField('user.auth.email'); const [email, emailAttrs] = defineField('user.auth.email');
const [password, passwordAttrs] = defineField('user.auth.password');
const [firstName, firstNameAttrs] = defineField('user.firstName'); const [firstName, firstNameAttrs] = defineField('user.firstName');
const [lastName, lastNameAttrs] = defineField('user.lastName'); const [lastName, lastNameAttrs] = defineField('user.lastName');
const [dateOfBirth/*, dateOfBirthAttrs*/] = defineField('user.dateOfBirth'); // const [dateOfBirth, dateOfBirthAttrs] = defineField('formattedDate');
const [gender, genderAttrs] = defineField('gender'); const [gender, genderAttrs] = defineField('gender');
const [bats, batsAttrs] = defineField('bats'); const [bats, batsAttrs] = defineField('bats');
const [throws, throwsAttrs] = defineField('throws'); const [throws, throwsAttrs] = defineField('throws');
@ -135,35 +173,6 @@ const [jerseyNumber, jerseyNumberAttrs] = defineField('jerseyNumber');
const [weight, weightAttrs] = defineField('weight'); const [weight, weightAttrs] = defineField('weight');
const [height, heightAttrs] = defineField('height'); const [height, heightAttrs] = defineField('height');
const onDateChange = (value: string) => {
const input = value as string;
if (input) {
const parsedDate = dayjs(input, 'YYYY-MM-DD', true);
if (parsedDate.isValid()) {
setFieldValue('user.dateOfBirth', parsedDate.toDate());
} else {
setFieldValue('user.dateOfBirth', new Date());
}
} else {
setFieldValue('user.dateOfBirth', new Date());
}
formattedDate.value = value; // Update formatted string
player.value.user.dateOfBirth = new Date(value); // Convert to Date object and update
};
// Convert current value to yyyy-MM-dd for input
const dateValueString = computed(() => {
return dayjs(dateOfBirth.value).isValid()
? dayjs(dateOfBirth.value).format('YYYY-MM-DD')
: '';
});
const cancel = () => {
router.push('/home');
}
</script> </script>
<template> <template>
@ -180,210 +189,171 @@ const cancel = () => {
<ion-content class="ion-padding"> <ion-content class="ion-padding">
<form @submit="submit"> <form @submit="submit">
<ion-grid> <ion-card>
<ion-row> <ion-card-header>
<ion-col> <ion-card-title>Personal Data</ion-card-title>
<ion-item> </ion-card-header>
<Field name="user.auth.email"> <ion-card-content>
<ion-input required <!-- <CrudField name="user.email" label="Email" labelPlacement="floating"/>-->
label="E-Mail" <ion-item>
label-placement="stacked" <Field name="email">
v-model="email" <ion-input
v-bind="emailAttrs" readonly: true
type="email" label="E-Mail"
> label-placement="stacked"
<small v-if="errors['user.auth.email']" class="error-message">{{ errors['user.auth.email'] }}</small> v-model="email"
</ion-input> v-bind="emailAttrs"
</Field> type="email"
</ion-item> >
</ion-col> <small v-if="errors['user.email']" class="error-message">{{ errors['user.email'] }}</small>
</ion-row> </ion-input>
<ion-row v-if="mode === 'create'"> </Field>
<ion-col> </ion-item>
<ion-item>
<Field name="user.auth.password"> <ion-item>
<ion-input required <Field name="firstName">
label="Password" <ion-input
label-placement="stacked" readonly: true
v-model="password" label="First Name"
v-bind="passwordAttrs" label-placement="stacked"
type="password" v-model="firstName"
> v-bind="firstNameAttrs"
<ion-input-password-toggle slot="end"></ion-input-password-toggle> type="text"
<small v-if="errors['user.auth.password']" class="error-message">{{ errors['user.auth.password'] }}</small> >
</ion-input> <small v-if="errors['user.firstName']" class="error-message">{{ errors['user.firstName'] }}</small>
</Field> </ion-input>
</ion-item> </Field>
</ion-col> </ion-item>
</ion-row>
<ion-row> <ion-item>
<ion-col> <Field name="lastName">
<ion-item> <ion-input
<Field name="user.firstName"> label="Last Name"
<ion-input label-placement="stacked"
label="First Name" v-model="lastName"
label-placement="stacked" v-bind="lastNameAttrs"
v-model="firstName" type="text"
v-bind="firstNameAttrs" >
type="text"> <small v-if="errors['user.lastName']" class="error-message">{{ errors['user.lastName'] }}</small>
<small v-if="errors['user.firstName']" class="error-message">{{ errors['user.firstName'] }}</small> </ion-input>
</ion-input> </Field>
</Field> </ion-item>
</ion-item>
</ion-col> <ion-item>
</ion-row> <Field name="dateOfBirth">
<ion-row> <ion-input
<ion-col> label="Date of Birth"
<ion-item> label-placement="stacked"
<Field name="user.lastName"> v-model="formattedDate"
<ion-input @input="onDateChange($event.target.value)"
label="Last Name" type="date"
label-placement="stacked" >
v-model="lastName" <small v-if="errors['user.dateOfBirth']" class="error-message">{{ errors['user.dateOfBirth'] }}</small>
v-bind="lastNameAttrs" </ion-input>
type="text" </Field>
> </ion-item>
<small v-if="errors['user.lastName']" class="error-message">{{ errors['user.lastName'] }}</small> </ion-card-content>
</ion-input> </ion-card>
</Field>
</ion-item> <ion-card>
</ion-col> <ion-card-header>
</ion-row> <ion-card-title>Player Data</ion-card-title>
<ion-row> </ion-card-header>
<ion-col> <ion-card-content>
<ion-item> <ion-item>
<Field name="user.dateOfBirth"> <Field name="gender">
<ion-input <ion-select
label="Date of Birth" label="Gender"
label-placement="stacked" label-placement="stacked"
:value="dateValueString" v-model="gender"
@input="onDateChange($event.target.value)" v-bind="genderAttrs"
type="date" interface="action-sheet"
> >
<small v-if="errors['user.dateOfBirth']" class="error-message">{{ errors['user.dateOfBirth'] }}</small> <ion-select-option value="male">Male</ion-select-option>
</ion-input> <ion-select-option value="female">Female</ion-select-option>
</Field> <ion-select-option value="other">Diverse</ion-select-option>
</ion-item> </ion-select>
</ion-col> </Field>
</ion-row> </ion-item>
<ion-row>
<ion-col> <ion-item>
<ion-item> <Field name="bats">
<Field name="gender"> <ion-select
<ion-select label="Bats"
label="Gender" label-placement="stacked"
label-placement="stacked" v-model="bats"
v-model="gender" v-bind="batsAttrs"
v-bind="genderAttrs" interface="action-sheet"
interface="action-sheet" >
> <ion-select-option value="right">Right</ion-select-option>
<ion-select-option value="male">Male</ion-select-option> <ion-select-option value="left">Left</ion-select-option>
<ion-select-option value="female">Female</ion-select-option> <ion-select-option value="both">Switch</ion-select-option>
<ion-select-option value="other">Diverse</ion-select-option> </ion-select>
</ion-select> </Field>
</Field> </ion-item>
</ion-item>
</ion-col> <ion-item>
</ion-row> <Field name="throws">
<ion-row> <ion-select
<ion-col> label="Throws"
<ion-item> label-placement="stacked"
<Field name="bats"> v-model="throws"
<ion-select v-bind="throwsAttrs"
label="Bats" interface="action-sheet"
label-placement="stacked" >
v-model="bats" <ion-select-option value="right">Right</ion-select-option>
v-bind="batsAttrs" <ion-select-option value="left">Left</ion-select-option>
interface="action-sheet" </ion-select>
> </Field>
<ion-select-option value="right">Right</ion-select-option> </ion-item>
<ion-select-option value="left">Left</ion-select-option>
<ion-select-option value="both">Switch</ion-select-option> <ion-item>
</ion-select> <Field name="jerseyNumber">
</Field> <ion-input
</ion-item> label="Jersey Number"
</ion-col> label-placement="stacked"
<ion-col> v-model="jerseyNumber"
<ion-item> v-bind="jerseyNumberAttrs"
<Field name="throws"> type="number"
<ion-select >
label="Throws" <small v-if="errors.jerseyNumber" class="error-message">{{ errors.jerseyNumber }}</small>
label-placement="stacked" </ion-input>
v-model="throws" </Field>
v-bind="throwsAttrs" </ion-item>
interface="action-sheet"
> <ion-item>
<ion-select-option value="right">Right</ion-select-option> <Field name="weight">
<ion-select-option value="left">Left</ion-select-option> <ion-input
</ion-select> label="Weight (kg)"
</Field> label-placement="stacked"
</ion-item> v-model="weight"
</ion-col> v-bind="weightAttrs"
</ion-row> type="number"
<ion-row> >
<ion-col> <small v-if="errors.weight" class="error-message">{{ errors.weight }}</small>
<ion-item> </ion-input>
<Field name="jerseyNumber"> </Field>
<ion-input </ion-item>
label="Jersey Number"
label-placement="stacked" <ion-item>
v-model="jerseyNumber" <Field name="height">
v-bind="jerseyNumberAttrs" <ion-input
type="number" label="Height (cm)"
> label-placement="stacked"
<small v-if="errors.jerseyNumber" class="error-message">{{ errors.jerseyNumber }}</small> v-model="height"
</ion-input> v-bind="heightAttrs"
</Field> type="number"
</ion-item> >
</ion-col> <small v-if="errors.height" class="error-message">{{ errors.height }}</small>
</ion-row> </ion-input>
<ion-row> </Field>
<ion-col> </ion-item>
<ion-item> </ion-card-content>
<Field name="weight"> </ion-card>
<ion-input
label="Weight (kg)" <div class="ion-padding-vertical">
label-placement="stacked" <ion-button type="submit" expand="block">Save</ion-button>
v-model="weight" </div>
v-bind="weightAttrs"
type="number"
>
<small v-if="errors.weight" class="error-message">{{ errors.weight }}</small>
</ion-input>
</Field>
</ion-item>
</ion-col>
<ion-col>
<ion-item>
<Field name="height">
<ion-input
label="Height (cm)"
label-placement="stacked"
v-model="height"
v-bind="heightAttrs"
type="number"
>
<small v-if="errors.height" class="error-message">{{ errors.height }}</small>
</ion-input>
</Field>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-button expand="block" color="danger" @click="cancel">
Cancel
<ion-icon slot="end" :icon="stop"></ion-icon>
</ion-button>
</ion-col>
<ion-col>
<ion-button type="submit" expand="block" color="success">
Save
<ion-icon slot="end" :icon="save"></ion-icon>
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</form> </form>
</ion-content> </ion-content>
</ion-page> </ion-page>

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import {personOutline} from "ionicons/icons"; import {logOutOutline, personOutline, playOutline, statsChartOutline} from "ionicons/icons";
import { import {
IonAvatar, IonAvatar,
IonButton, IonButton,
@ -11,38 +11,19 @@ import {
IonTitle, IonTitle,
IonToolbar IonToolbar
} from "@ionic/vue"; } from "@ionic/vue";
import {computed, onMounted, ref} from "vue"; import {computed, ref} from "vue";
import {useStore} from "vuex"; import {useStore} from "vuex";
import {useRoute, useRouter} from "vue-router"; import {useRouter} from "vue-router";
import PlayerService from "@/services/PlayerService";
// import dayjs from "dayjs";
const userImage = ref(null); const userImage = ref(null);
const router = useRouter(); const router = useRouter();
const route = useRoute();
const store = useStore(); const store = useStore();
const id = route.params.id as string | undefined; // `id` parameter from route
const pitcher = computed(() => store.state.auth.user); const pitcher = computed(() => store.state.auth.user);
const isAuthenticated = computed(() => store.state.auth.isAuthenticated); const isAuthenticated = computed(() => store.state.auth.isAuthenticated);
onMounted(() => {
PlayerService
.fetchByUserId(Number(id))
.then((response) => {
console.log('Fetched player:', response);
// player.value = response;
// resetForm({ values: { ...player.value } }); // Reset form with fetched data
// formattedDate.value = dayjs(player.value.user.dateOfBirth).format('YYYY-MM-DD');
})
.catch((error) => {
console.error('Failed to fetch player:', error);
});
});
const gotoHome = () => { const gotoHome = () => {
router.push({path: '/home'}); router.push({path: '/home'});
} }

View File

@ -18,7 +18,6 @@ module.exports = {
await createUsers(queryInterface, roles, [ await createUsers(queryInterface, roles, [
{ email: 'sparky.anderson@bullpen.com', password: 'sparky$123', firstName: 'Sparky', lastName: 'Anderson', dateOfBirth: new Date(1934, 1, 22), roles: ['coach', 'admin'] }, { email: 'sparky.anderson@bullpen.com', password: 'sparky$123', firstName: 'Sparky', lastName: 'Anderson', dateOfBirth: new Date(1934, 1, 22), roles: ['coach', 'admin'] },
{ email: 'c@d', password: 'demo$123', firstName: 'Demo', lastName: 'Coach', dateOfBirth: new Date(1970, 1, 22), roles: ['coach', 'admin'] },
]); ]);
}, },