From 787b9879fc638d33b72a9c667a242b62cdb2519e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Mon, 28 Apr 2025 22:49:22 +0200 Subject: [PATCH] frontend and backend progress --- app/Dockerfile | 13 ++++ app/package-lock.json | 2 +- app/package.json | 1 + app/src/App.vue | 3 + app/src/router/index.ts | 2 + app/src/services/BackendService.ts | 4 +- app/src/views/BullpenListView.vue | 38 ++++++++++- app/src/views/LoginView.vue | 7 +- app/src/views/ProfileView.vue | 102 +++++++++++++++++++++++++++++ backend/config/auth.config.js | 8 +-- 10 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 app/Dockerfile create mode 100644 app/src/views/ProfileView.vue diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..a03aca0 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,13 @@ +# build stage +FROM node:lts-alpine AS build-stage +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +# production stage +FROM nginx:stable-alpine AS production-stage +COPY --from=build-stage /app/dist /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/app/package-lock.json b/app/package-lock.json index e324e94..0072386 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -17,6 +17,7 @@ "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", "axios": "^1.8.1", + "dayjs": "^1.11.13", "ionicons": "^7.0.0", "vee-validate": "^4.15.0", "vue": "^3.3.0", @@ -4962,7 +4963,6 @@ "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "dev": true, "license": "MIT" }, "node_modules/de-indent": { diff --git a/app/package.json b/app/package.json index 3aa79e8..dd9a425 100644 --- a/app/package.json +++ b/app/package.json @@ -21,6 +21,7 @@ "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", "axios": "^1.8.1", + "dayjs": "^1.11.13", "ionicons": "^7.0.0", "vee-validate": "^4.15.0", "vue": "^3.3.0", diff --git a/app/src/App.vue b/app/src/App.vue index 56cb886..4efcc13 100644 --- a/app/src/App.vue +++ b/app/src/App.vue @@ -5,6 +5,7 @@ import { useStore } from 'vuex' import { AppStore } from '@/store'; import { onMounted, onBeforeUnmount, ref } from "vue"; import EventBus from "./common/EventBus"; +import backendService from '@/services/BackendService' const router = useRouter(); const store = useStore(); @@ -19,6 +20,8 @@ const isOnline = ref(navigator.onLine); onMounted(() => { EventBus.on("logout", logout); + backendService.updateServer(backendService.getServer()); + window.addEventListener("online", () => isOnline.value = true); window.addEventListener("offline", () => isOnline.value = false); diff --git a/app/src/router/index.ts b/app/src/router/index.ts index c4edd58..9b1152a 100644 --- a/app/src/router/index.ts +++ b/app/src/router/index.ts @@ -9,12 +9,14 @@ import BullpenSummaryView from "@/views/BullpenSummaryView.vue"; import SetupView from '@/views/SetupView.vue'; import backendService from '@/services/BackendService' import BullpenListView from "@/views/BullpenListView.vue"; +import ProfileView from "@/views/ProfileView.vue"; const routes: Array = [ { path: '/', redirect: '/login' }, { path: '/login', component: LoginView }, { path: '/setup', component: SetupView }, { path: '/home', component: HomeView }, + { path: '/profile', component: ProfileView }, { path: '/pitchers', component: PitcherList }, { path: '/bullpen', component: BullpenView }, { path: '/stats', component: BullpenListView }, diff --git a/app/src/services/BackendService.ts b/app/src/services/BackendService.ts index aa787d5..5d07dcd 100644 --- a/app/src/services/BackendService.ts +++ b/app/src/services/BackendService.ts @@ -5,8 +5,8 @@ class BackendService { return localStorage.getItem("server") !== null; } getServer(): Server { - return JSON.parse(localStorage.getItem("server") || '{"protocol":"http","host":"localhost","port":8080}'); - // return JSON.parse(localStorage.getItem("server") || '{"protocol":"https","host":"bullpen-api.palaeomatiker.home64.de","port":443}'); + // return JSON.parse(localStorage.getItem("server") || '{"protocol":"http","host":"localhost","port":8080}'); + return JSON.parse(localStorage.getItem("server") || '{"protocol":"https","host":"bullpen-api.palaeomatiker.home64.de","port":443}'); } updateServer(server: Server): void { localStorage.setItem("server", JSON.stringify(server)); diff --git a/app/src/views/BullpenListView.vue b/app/src/views/BullpenListView.vue index 8c0fcd0..0993b14 100644 --- a/app/src/views/BullpenListView.vue +++ b/app/src/views/BullpenListView.vue @@ -2,17 +2,24 @@ import { IonButton, IonCard, + IonCardTitle, + IonCardSubtitle, IonContent, IonFooter, IonHeader, - IonLabel, IonPage, IonTitle, - IonToolbar + IonToolbar, IonLabel, IonList, IonItem, IonIcon, IonBadge } from "@ionic/vue"; +import { + baseballOutline +} from 'ionicons/icons'; + +import PitchType from "@/types/PitchType"; import {useStore} from 'vuex'; import {useRouter} from 'vue-router'; import {computed} from "vue"; +import dayjs from 'dayjs'; const router = useRouter(); const store = useStore(); @@ -20,6 +27,17 @@ const store = useStore(); const isAuthenticated = computed(() => store.state.auth.isAuthenticated); const pitcher = computed(() => store.state.auth.user); const bullpens = computed(() => store.state.bullpen.bullpens); +const pitchTypes = computed(() => store.state.pitchTypes.pitchTypes); + +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 gotoHome = () => { router.push({path: '/home'}); @@ -37,7 +55,21 @@ const gotoHome = () => { - Bullpen {{bullpen.id}} ({{bullpen.startedAt}}) + + Bullpen from ({{formatDate(bullpen.startedAt)}}) + + + + + + + {{determinePitchTypeName(pitch.pitchTypeId)}} + {{pitch.aimedArea}} + {{pitch.hitArea}} + + + + diff --git a/app/src/views/LoginView.vue b/app/src/views/LoginView.vue index 61f702f..726d289 100644 --- a/app/src/views/LoginView.vue +++ b/app/src/views/LoginView.vue @@ -3,7 +3,7 @@ import { computed, ref, onMounted } from "vue"; import { IonPage, IonIcon, - IonLabel, + // IonLabel, IonButton, IonContent, IonInput @@ -20,11 +20,10 @@ import { useRouter } from 'vue-router'; import { useStore } from 'vuex' import * as yup from 'yup'; import PitchTypeService from "@/services/PitchTypeService"; -import EventBus from "@/common/EventBus"; import PitchType from "@/types/PitchType"; const loading = ref(false); -const server = JSON.parse(localStorage.getItem("server") || '""'); +// const server = JSON.parse(localStorage.getItem("server") || '""'); const schema = yup.object({ email: yup.string().email('Invalid email address').required('Email is required'), @@ -100,7 +99,7 @@ const changeServer = () => {
- {{server.protocol}}://{{server.host}}:{{server.port}} +
diff --git a/app/src/views/ProfileView.vue b/app/src/views/ProfileView.vue new file mode 100644 index 0000000..b6a022f --- /dev/null +++ b/app/src/views/ProfileView.vue @@ -0,0 +1,102 @@ + + + + + \ No newline at end of file diff --git a/backend/config/auth.config.js b/backend/config/auth.config.js index 35762f3..b5a8b04 100644 --- a/backend/config/auth.config.js +++ b/backend/config/auth.config.js @@ -1,10 +1,10 @@ module.exports = { secret: "bullpen-secret-key", - // jwtExpiration: 3600, // 1 hour - // jwtRefreshExpiration: 86400, // 24 hours + jwtExpiration: 3600, // 1 hour + jwtRefreshExpiration: 86400 * 7, // 7 days /* for test */ - jwtExpiration: 30, // 30 seconds - jwtRefreshExpiration: 60 // 1 minute + // jwtExpiration: 30, // 30 seconds + // jwtRefreshExpiration: 60 // 1 minute };