Compare commits

...

2 Commits

Author SHA1 Message Date
Sascha Kühl a18bbff1e2 restructured login 2025-04-30 17:25:27 +02:00
Sascha Kühl 4108388645 added missing imports,removed obsolete code 2025-04-30 17:25:12 +02:00
3 changed files with 78 additions and 119 deletions

View File

@ -18,7 +18,6 @@
<link rel="shortcut icon" type="image/png" href="/favicon.png" /> <link rel="shortcut icon" type="image/png" href="/favicon.png" />
<!-- add to homescreen for ios --> <!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Ionic App" /> <meta name="apple-mobile-web-app-title" content="Ionic App" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
</head> </head>

View File

@ -2,19 +2,15 @@
import { computed, ref, onMounted } from "vue"; import { computed, ref, onMounted } from "vue";
import { import {
IonPage, IonPage,
IonIcon,
// IonLabel,
IonButton, IonButton,
IonContent, IonCard,
IonInput IonInput,
IonItem,
IonCardHeader,
IonCardTitle,
IonCardContent,
} from "@ionic/vue"; } from "@ionic/vue";
import {
lockClosedOutline,
personOutline,
// arrowBack,
// shapesOutline
} from 'ionicons/icons';
import {Field, useForm} from 'vee-validate'; import {Field, useForm} from 'vee-validate';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex' import { useStore } from 'vuex'
@ -91,82 +87,74 @@ const changeServer = () => {
<template> <template>
<ion-page> <ion-page>
<ion-content> <div class="background-grid">
<div class="login-container"> <div class="top-half">
<div class="top-section"> <div class="logo-container">
<h1 class="login-title">Login</h1> <img src="../assets/Bonn_Capitals_Insignia.png" alt="Logo" class="logo" />
<div class="logo-container">
<img src="../assets/Bonn_Capitals_Insignia.png" alt="Logo" class="logo" />
</div>
<!-- <ion-label>{{server.protocol}}://{{server.host}}:{{server.port}}</ion-label>-->
</div> </div>
<form @submit="submit" class="form-container"> </div>
<div class="input-group"> <div class="bottom-half"></div>
<div class="label-row"> </div>
<label class="input-label" for="email">Email</label> <!-- Centered card container -->
<small v-if="!meta.valid" class="error-message">{{ errors.email }}</small> <div class="card-container">
</div> <ion-card>
<Field id="email" name="email" type="email" > <ion-card-header>
<div class="input-with-icon"> <ion-card-title>Login</ion-card-title>
<ion-icon :icon="personOutline" class="icon-login"></ion-icon> </ion-card-header>
<ion-input <ion-card-content>
name="email" <form @submit="submit">
<ion-item>
<Field id="email" name="email" type="email">
<ion-input required
label="Email"
label-placement="stacked"
v-model="email" v-model="email"
v-bind="emailAttrs" v-bind="emailAttrs"
class="rounded-input"
:class="{ 'input-invalid': !meta.valid && errors.email }" :class="{ 'input-invalid': !meta.valid && errors.email }"
type="text" required placeholder="Email"></ion-input> id="email"
</div> name="email"
</Field> type="email">
</div> <small v-if="!meta.valid" class="error-message">{{ errors.email }}</small>
</ion-input>
<div class="input-group"> </Field>
<div class="label-row"> </ion-item>
<label class="input-label" for="password">Password</label> <ion-item>
<small v-if="!meta.valid" class="error-message">{{ errors.password }}</small> <Field id="password" name="password" type="password">
</div> <ion-input required
<Field id="password" name="password" type="password"> label="Password"
<div class="input-with-icon"> label-placement="stacked"
<ion-icon :icon="lockClosedOutline" class="icon-login"></ion-icon>
<ion-input
name="password"
v-model="password" v-model="password"
v-bind="passwordAttrs" v-bind="passwordAttrs"
type="password"
class="rounded-input"
:class="{ 'input-invalid': !meta.valid && errors.password }" :class="{ 'input-invalid': !meta.valid && errors.password }"
required placeholder="Password"></ion-input> id="password"
</div> name="password"
</Field> type="password">
</div> </ion-input>
</Field>
<ion-button expand="block" class="rounded-button" type="submit">Login</ion-button> </ion-item>
<ion-button expand="block" class="rounded-button" @click="changeServer">Change Server</ion-button> <ion-button expand="block" class="ion-margin-top" type="submit" @click="submit">Login</ion-button>
</form> </form>
</div> </ion-card-content>
</ion-content> </ion-card>
</div>
</ion-page> </ion-page>
</template> </template>
<style scoped> <style scoped>
.login-container { .background-grid {
display: flex; display: grid;
flex-direction: column; grid-template-rows: 1fr 1fr;
align-items: center; height: 100vh;
} }
.top-section { .top-half {
background-color: #cbeec9; background: -moz-linear-gradient(180deg, rgba(106, 191, 102, 1) 0%, rgba(52, 94, 50, 0.8) 100%);
width: 100%; background: -webkit-linear-gradient(180deg, rgba(106, 191, 102, 1) 0%, rgba(52, 94, 50, 0.8) 100%);
display: flex; background: linear-gradient(180deg, rgba(106, 191, 102, 1) 0%, rgba(52, 94, 50, 0.8) 100%);
flex-direction: column;
align-items: center;
} }
.login-title { .bottom-half {
font-size: 2rem; background: #ffffff; /* or your bottom background */
margin-bottom: 1rem;
} }
.logo-container { .logo-container {
@ -174,6 +162,7 @@ const changeServer = () => {
display: flex; display: flex;
justify-content: center; justify-content: center;
height: 25vh; height: 25vh;
margin-top: 2rem;
padding-bottom: 1rem; padding-bottom: 1rem;
} }
@ -183,50 +172,22 @@ const changeServer = () => {
object-fit: cover; object-fit: cover;
} }
.form-container { .card-container {
padding-top: 1rem; position: absolute;
padding-left: 1rem; top: 0;
padding-right: 1rem; left: 0;
width: 100%; height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none; /* optional: allows background interaction */
}
ion-card {
width: 90%;
max-width: 400px; max-width: 400px;
} pointer-events: all; /* re-enables interactions for card */
.input-group {
width: 100%;
display: flex;
flex-direction: column;
position: relative;
margin-bottom: 16px;
}
.label-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4px;
}
.input-label {
font-size: 0.9rem;
margin-bottom: 4px;
text-align: left;
}
.input-with-icon {
display: flex;
align-items: center;
padding: 8px 0;
gap: 8px;
}
.rounded-input {
--border-radius: 50%;
padding: 12px;
background-color: #ffffff;
}
.input-invalid {
background-color: lightcoral;
} }
.error-message { .error-message {
@ -236,9 +197,8 @@ const changeServer = () => {
margin-top: 4px; margin-top: 4px;
} }
.rounded-button { .input-invalid {
--border-radius: 12px; background-color: lightcoral;
width: 100%;
} }
</style> </style>

View File

@ -2,7 +2,7 @@
import {ref} from 'vue'; import {ref} from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import backendService from '@/services/BackendService' import backendService from '@/services/BackendService'
import {IonButton, IonContent, IonCol, IonHeader, IonInput, IonPage, IonTitle, IonToolbar, IonCheckbox} from '@ionic/vue'; import {IonButton, IonContent, IonCol, IonHeader, IonInput, IonPage, IonTitle, IonToolbar, IonRow, IonCheckbox} from '@ionic/vue';
const server = ref(backendService.getServer()); const server = ref(backendService.getServer());