Better validation on text fields, change AlertBanner to Snackbar
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
"id": 0,
|
"id": 0,
|
||||||
"username": "hagemeister93",
|
"username": "hagemeister93",
|
||||||
"password": "Xjt3qb5t",
|
"password": "Xjt3qb5t",
|
||||||
|
"email": "hagemeister93@gmail.com",
|
||||||
"firstName": "Laurin",
|
"firstName": "Laurin",
|
||||||
"lastName": "Hagemeister",
|
"lastName": "Hagemeister",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"id": 1,
|
"id": 1,
|
||||||
"username": "katjaStoiber",
|
"username": "katjaStoiber",
|
||||||
"password": "target123",
|
"password": "target123",
|
||||||
|
"email": "k.stoiber@uni-hannover.de",
|
||||||
"firstName": "Katja",
|
"firstName": "Katja",
|
||||||
"lastName": "Stoiber",
|
"lastName": "Stoiber",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -52,6 +54,7 @@
|
|||||||
"id": 2,
|
"id": 2,
|
||||||
"username": "oetkerohnek",
|
"username": "oetkerohnek",
|
||||||
"password": "iloveyou",
|
"password": "iloveyou",
|
||||||
|
"email": "oetker30625@gmx.com",
|
||||||
"firstName": "Luna",
|
"firstName": "Luna",
|
||||||
"lastName": "Oeter",
|
"lastName": "Oeter",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -83,6 +86,7 @@
|
|||||||
"id": 3,
|
"id": 3,
|
||||||
"username": "duranduran",
|
"username": "duranduran",
|
||||||
"password": "H4nn0ver",
|
"password": "H4nn0ver",
|
||||||
|
"email": "dduran@hannover.de",
|
||||||
"firstName": "Jürgen",
|
"firstName": "Jürgen",
|
||||||
"lastName": "Durand",
|
"lastName": "Durand",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -114,6 +118,7 @@
|
|||||||
"id": 4,
|
"id": 4,
|
||||||
"username": "guitarhero",
|
"username": "guitarhero",
|
||||||
"password": "gwerty123",
|
"password": "gwerty123",
|
||||||
|
"email": "guitarheroFurti@gmail.com",
|
||||||
"firstName": "Frederik",
|
"firstName": "Frederik",
|
||||||
"lastName": "Furtwängler",
|
"lastName": "Furtwängler",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -138,6 +143,7 @@
|
|||||||
"id": 5,
|
"id": 5,
|
||||||
"username": "herbstMareike",
|
"username": "herbstMareike",
|
||||||
"password": "qhsrbpgrs",
|
"password": "qhsrbpgrs",
|
||||||
|
"email": "m.herbst@uni-hannover.de",
|
||||||
"firstName": "Mareike",
|
"firstName": "Mareike",
|
||||||
"lastName": "Herbst",
|
"lastName": "Herbst",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
@@ -162,6 +168,7 @@
|
|||||||
"id": 6,
|
"id": 6,
|
||||||
"username": "seibertmitb",
|
"username": "seibertmitb",
|
||||||
"password": "{jkz+WvQe",
|
"password": "{jkz+WvQe",
|
||||||
|
"email": "janna-seibert@yahoo.com",
|
||||||
"firstName": "Janna",
|
"firstName": "Janna",
|
||||||
"lastName": "Seibert",
|
"lastName": "Seibert",
|
||||||
"addresses": [
|
"addresses": [
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ export class Account extends Model {
|
|||||||
@Column
|
@Column
|
||||||
password: string
|
password: string
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
@Column
|
||||||
|
email: string
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
firstName: string = ""
|
firstName: string = ""
|
||||||
|
|
||||||
|
|||||||
@@ -78,11 +78,29 @@ account.post("/", (req: Request, res: Response) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
account.patch("/", (req: Request, res: Response) => {
|
account.patch("/", (req: Request, res: Response) => {
|
||||||
|
console.log(req.body)
|
||||||
|
|
||||||
Account.update(req.body,
|
Account.update(req.body,
|
||||||
{
|
{
|
||||||
where: { id: req.body.id }
|
where: { id: req.body.id }
|
||||||
})
|
})
|
||||||
.then(account => {
|
.then(async account => {
|
||||||
|
for (let payment of req.body.payments) {
|
||||||
|
await Payment.update(payment,
|
||||||
|
{
|
||||||
|
where: { id: payment.id }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let address of req.body.addresses) {
|
||||||
|
await Address.update(address,
|
||||||
|
{
|
||||||
|
where: { id: address.id }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Status: 200 OK
|
// Status: 200 OK
|
||||||
res.status(200).json(account)
|
res.status(200).json(account)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import navigationItems from './components/navigationItems.vue';
|
|||||||
import { useProductStore } from './data/stores/productStore';
|
import { useProductStore } from './data/stores/productStore';
|
||||||
import { useCategoryStore } from './data/stores/categoryStore';
|
import { useCategoryStore } from './data/stores/categoryStore';
|
||||||
import { usePreferencesStore } from './data/stores/preferencesStore';
|
import { usePreferencesStore } from './data/stores/preferencesStore';
|
||||||
|
import { useFeedbackStore } from './data/stores/feedbackStore';
|
||||||
|
|
||||||
const preferencesStore = usePreferencesStore()
|
const preferencesStore = usePreferencesStore()
|
||||||
const productStore = useProductStore()
|
const productStore = useProductStore()
|
||||||
const categoryStore = useCategoryStore()
|
const categoryStore = useCategoryStore()
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const navRail = ref(vuetify.display.mobile)
|
const navRail = ref(vuetify.display.mobile)
|
||||||
|
|
||||||
@@ -38,6 +40,26 @@ watch(() => preferencesStore.language, () => {
|
|||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
|
||||||
<v-main>
|
<v-main>
|
||||||
|
<!-- Snackbar in the top right corner for user feedback -->
|
||||||
|
<v-snackbar
|
||||||
|
v-model="feedbackStore.showBanner"
|
||||||
|
timeout="3000"
|
||||||
|
location="top right"
|
||||||
|
:color="feedbackStore.color"
|
||||||
|
close
|
||||||
|
>
|
||||||
|
<v-icon :icon="feedbackStore.icon" />
|
||||||
|
{{ feedbackStore.title }}
|
||||||
|
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn
|
||||||
|
variant="text"
|
||||||
|
@click="feedbackStore.showBanner = false"
|
||||||
|
icon="mdi-close"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
|
||||||
<!-- Here changes the router the content -->
|
<!-- Here changes the router the content -->
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</v-main>
|
</v-main>
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
|
||||||
|
|
||||||
const feedbackStore = useFeedbackStore()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<v-expand-transition>
|
|
||||||
<v-row v-if="feedbackStore.showBanner">
|
|
||||||
<v-col>
|
|
||||||
<v-alert
|
|
||||||
v-model="feedbackStore.showBanner"
|
|
||||||
:color="feedbackStore.color"
|
|
||||||
:icon="feedbackStore.icon"
|
|
||||||
closable
|
|
||||||
>
|
|
||||||
{{ feedbackStore.title }}
|
|
||||||
</v-alert>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-expand-transition>
|
|
||||||
</template>
|
|
||||||
@@ -6,6 +6,7 @@ export class AccountModel {
|
|||||||
id: number
|
id: number
|
||||||
username: string = ""
|
username: string = ""
|
||||||
password: string = ""
|
password: string = ""
|
||||||
|
email: string = ""
|
||||||
firstName: string = ""
|
firstName: string = ""
|
||||||
lastName: string = ""
|
lastName: string = ""
|
||||||
addresses: Array<AddressModel> = [ new AddressModel() ]
|
addresses: Array<AddressModel> = [ new AddressModel() ]
|
||||||
|
|||||||
@@ -71,7 +71,8 @@
|
|||||||
"masterData": "Stammdaten",
|
"masterData": "Stammdaten",
|
||||||
"noAddresses": "Keine Adressen gefunden",
|
"noAddresses": "Keine Adressen gefunden",
|
||||||
"noPayments": "Keine Bezahlarten gefunden",
|
"noPayments": "Keine Bezahlarten gefunden",
|
||||||
"newPayment": "New Payment"
|
"newPayment": "New Payment",
|
||||||
|
"email": "E-Mail-Adresse"
|
||||||
},
|
},
|
||||||
"bannerMessages": {
|
"bannerMessages": {
|
||||||
"loginSuccessful": "Login erfolgreich!",
|
"loginSuccessful": "Login erfolgreich!",
|
||||||
@@ -127,5 +128,10 @@
|
|||||||
"noOrders": "Keine Bestellungen gefunden",
|
"noOrders": "Keine Bestellungen gefunden",
|
||||||
"noOrdersText": "Bisher wurden keine Bestellungen von diesem Account getätigt. Gehe zum Warenkorb und bestelle!",
|
"noOrdersText": "Bisher wurden keine Bestellungen von diesem Account getätigt. Gehe zum Warenkorb und bestelle!",
|
||||||
"add": "Hinzufügen",
|
"add": "Hinzufügen",
|
||||||
"remove": "Entfernen"
|
"remove": "Entfernen",
|
||||||
|
"emailIsNotValid": "Ungültige E-Mail Addresse",
|
||||||
|
"emailRequired": "E-Mail-Adresse benötigt",
|
||||||
|
"tooMuchChars": "Zu lang",
|
||||||
|
"digitsAtStartNeeded": "Muss mit einer Zahl beginnen",
|
||||||
|
"wrongIban": "Falsches IBAN Format, nur deutsche IBAN-Nummern erlaubt!"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,8 @@
|
|||||||
"masterData": "Master data",
|
"masterData": "Master data",
|
||||||
"noAddresses": "No Addresses found",
|
"noAddresses": "No Addresses found",
|
||||||
"noPayments": "No payments found",
|
"noPayments": "No payments found",
|
||||||
"newPayment": "New Payment"
|
"newPayment": "New Payment",
|
||||||
|
"email": "E-Mail address"
|
||||||
},
|
},
|
||||||
"bannerMessages": {
|
"bannerMessages": {
|
||||||
"loginSuccessful": "Login erfolgreich!",
|
"loginSuccessful": "Login erfolgreich!",
|
||||||
@@ -127,5 +128,10 @@
|
|||||||
"noOrders": "No orders found",
|
"noOrders": "No orders found",
|
||||||
"noOrdersText": "There are no orders with this account until now. Go to the basket page and order something!",
|
"noOrdersText": "There are no orders with this account until now. Go to the basket page and order something!",
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
"remove": "Remove"
|
"remove": "Remove",
|
||||||
|
"emailIsNotValid": "E-mail must be valid",
|
||||||
|
"emailRequired": "E-Mail is required",
|
||||||
|
"tooMuchChars": "Too long",
|
||||||
|
"digitsAtStartNeeded": "Has to beginn with a number",
|
||||||
|
"wrongIban": "Wrong IBAN format, only German IBANs are allowed!"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,51 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import outlinedButton from '@/components/outlinedButton.vue';
|
|
||||||
import { useAccountStore } from '@/data/stores/accountStore';
|
import { useAccountStore } from '@/data/stores/accountStore';
|
||||||
import { ref } from 'vue';
|
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
||||||
|
|
||||||
const accountStore = useAccountStore()
|
const accountStore = useAccountStore()
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
const passwordRules = [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value?.length >= 8) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('passwordToShort')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const stringRules = [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/[^0-9]/.test(value)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('noDigitsAllowed')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value?.length >= 3) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('notEnoughChars')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -12,6 +53,15 @@ const accountStore = useAccountStore()
|
|||||||
:title="$t('account.masterData')"
|
:title="$t('account.masterData')"
|
||||||
icon="mdi-account"
|
icon="mdi-account"
|
||||||
>
|
>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-text-field
|
||||||
|
:label="$t('account.email')"
|
||||||
|
v-model="accountStore.userAccount.email"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
@@ -25,6 +75,7 @@ const accountStore = useAccountStore()
|
|||||||
:label="$t('account.password')"
|
:label="$t('account.password')"
|
||||||
v-model="accountStore.userAccount.password"
|
v-model="accountStore.userAccount.password"
|
||||||
type="password"
|
type="password"
|
||||||
|
:rules="passwordRules"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -34,12 +85,14 @@ const accountStore = useAccountStore()
|
|||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.firstName')"
|
:label="$t('userInfo.firstName')"
|
||||||
v-model="accountStore.userAccount.firstName"
|
v-model="accountStore.userAccount.firstName"
|
||||||
|
:rules="stringRules"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.lastName')"
|
:label="$t('userInfo.lastName')"
|
||||||
v-model="accountStore.userAccount.lastName"
|
v-model="accountStore.userAccount.lastName"
|
||||||
|
:rules="stringRules"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import cardView from '@/components/cardView.vue';
|
|||||||
import { useAccountStore } from '@/data/stores/accountStore';
|
import { useAccountStore } from '@/data/stores/accountStore';
|
||||||
import outlinedButton from '@/components/outlinedButton.vue';
|
import outlinedButton from '@/components/outlinedButton.vue';
|
||||||
import { AddressModel } from '@/data/models/addressModel';
|
import { AddressModel } from '@/data/models/addressModel';
|
||||||
|
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
||||||
|
import { getNumberStartRules, getPostalRules, getStringRules } from '@/scripts/validationRules';
|
||||||
|
|
||||||
const accountStore = useAccountStore()
|
const accountStore = useAccountStore()
|
||||||
</script>
|
</script>
|
||||||
@@ -27,12 +29,16 @@ const accountStore = useAccountStore()
|
|||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.street')"
|
:label="$t('userInfo.street')"
|
||||||
v-model="address.street"
|
v-model="address.street"
|
||||||
|
:rules="getStringRules()"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.houseNumber')"
|
:label="$t('userInfo.houseNumber')"
|
||||||
v-model="address.houseNumber"
|
v-model="address.houseNumber"
|
||||||
|
:rules="getNumberStartRules()"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -42,12 +48,16 @@ const accountStore = useAccountStore()
|
|||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.postalCode')"
|
:label="$t('userInfo.postalCode')"
|
||||||
v-model="address.postalCode"
|
v-model="address.postalCode"
|
||||||
|
:rules="getPostalRules()"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.city')"
|
:label="$t('userInfo.city')"
|
||||||
v-model="address.city"
|
v-model="address.city"
|
||||||
|
:rules="getStringRules()"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import cardView from '@/components/cardView.vue';
|
|||||||
import { useAccountStore } from '@/data/stores/accountStore';
|
import { useAccountStore } from '@/data/stores/accountStore';
|
||||||
import outlinedButton from '@/components/outlinedButton.vue';
|
import outlinedButton from '@/components/outlinedButton.vue';
|
||||||
import { PaymentModel } from '@/data/models/paymentModel';
|
import { PaymentModel } from '@/data/models/paymentModel';
|
||||||
|
import { getIbanRules, getStringRules } from '@/scripts/validationRules';
|
||||||
|
|
||||||
const accountStore = useAccountStore()
|
const accountStore = useAccountStore()
|
||||||
|
|
||||||
@@ -29,12 +30,14 @@ const accountStore = useAccountStore()
|
|||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.bankName')"
|
:label="$t('userInfo.bankName')"
|
||||||
v-model="payment.bankName"
|
v-model="payment.bankName"
|
||||||
|
:rules="getStringRules()"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.iban')"
|
:label="$t('userInfo.iban')"
|
||||||
v-model="payment.iban"
|
v-model="payment.iban"
|
||||||
|
:rules="getIbanRules()"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useBasketStore } from '@/data/stores/basketStore';
|
import { useBasketStore } from '@/data/stores/basketStore';
|
||||||
import productsTable from './productsTable.vue';
|
import productsTable from './productsTable.vue';
|
||||||
import alertBanner from '@/components/alertBanner.vue';
|
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import orderingDialog from './orderingDialog.vue';
|
import orderingDialog from './orderingDialog.vue';
|
||||||
import outlinedButton from '@/components/outlinedButton.vue';
|
import outlinedButton from '@/components/outlinedButton.vue';
|
||||||
@@ -15,11 +14,6 @@ const showOrderingDialog = ref()
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="1000">
|
<v-container max-width="1000">
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<alert-banner />
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<card-view
|
<card-view
|
||||||
|
|||||||
@@ -2,19 +2,12 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import loginForm from './loginForm.vue';
|
import loginForm from './loginForm.vue';
|
||||||
import registerForm from './registerForm.vue';
|
import registerForm from './registerForm.vue';
|
||||||
import alertBanner from '@/components/alertBanner.vue';
|
|
||||||
|
|
||||||
const showRegisterCard = ref(false)
|
const showRegisterCard = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="800">
|
<v-container max-width="500">
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<alert-banner />
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
<v-row v-if="!showRegisterCard">
|
<v-row v-if="!showRegisterCard">
|
||||||
<v-col>
|
<v-col>
|
||||||
|
|||||||
@@ -9,10 +9,28 @@ const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, defaul
|
|||||||
const loginInProgress = ref(false)
|
const loginInProgress = ref(false)
|
||||||
const username = ref("duranduran")
|
const username = ref("duranduran")
|
||||||
const password = ref("H4nn0ver")
|
const password = ref("H4nn0ver")
|
||||||
|
const usernameWrong = ref(false)
|
||||||
|
const passwordWrong = ref(false)
|
||||||
|
|
||||||
async function startLogin() {
|
async function startLogin() {
|
||||||
loginInProgress.value = true
|
loginInProgress.value = true
|
||||||
await accountStore.login(username.value, password.value)
|
usernameWrong.value = false
|
||||||
|
passwordWrong.value = false
|
||||||
|
|
||||||
|
if (username.value == null || username.value.length == 0) {
|
||||||
|
usernameWrong.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.value == null || password.value.length == 0) {
|
||||||
|
passwordWrong.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username.value != null && username.value.length > 0 &&
|
||||||
|
password.value != null && password.value.length > 0)
|
||||||
|
{
|
||||||
|
await accountStore.login(username.value, password.value)
|
||||||
|
}
|
||||||
|
|
||||||
loginInProgress.value = false
|
loginInProgress.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -21,14 +39,26 @@ async function startLogin() {
|
|||||||
<card-view :title="$t('menu.login')" prepend-icon="mdi-login" elevation="8">
|
<card-view :title="$t('menu.login')" prepend-icon="mdi-login" elevation="8">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field :label="$t('account.username')" prepend-icon="mdi-account" clearable v-model="username"/>
|
<v-text-field
|
||||||
|
:label="$t('account.username')"
|
||||||
|
prepend-icon="mdi-account"
|
||||||
|
v-model="username"
|
||||||
|
:error="usernameWrong"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field :label="$t('account.password')" prepend-icon="mdi-key" type="password"
|
<v-text-field
|
||||||
clearable v-model="password" />
|
:label="$t('account.password')"
|
||||||
|
prepend-icon="mdi-key"
|
||||||
|
type="password"
|
||||||
|
v-model="password"
|
||||||
|
:error="passwordWrong"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
|||||||
@@ -4,90 +4,14 @@ import { ref } from 'vue';
|
|||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import outlinedButton from '@/components/outlinedButton.vue';
|
import outlinedButton from '@/components/outlinedButton.vue';
|
||||||
import { useAccountStore } from '@/data/stores/accountStore';
|
import { useAccountStore } from '@/data/stores/accountStore';
|
||||||
import { i18n } from '@/plugins/i18n';
|
|
||||||
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
||||||
|
import { getEmailRules, getPasswordRules, getStringRules } from '@/scripts/validationRules';
|
||||||
|
|
||||||
const newUser = ref(new AccountModel())
|
const newUser = ref(new AccountModel())
|
||||||
const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
|
const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
|
||||||
const accountStore = useAccountStore()
|
const accountStore = useAccountStore()
|
||||||
const feedbackStore = useFeedbackStore()
|
|
||||||
const registerInProgress = ref(false)
|
const registerInProgress = ref(false)
|
||||||
|
|
||||||
const stringRules = [
|
|
||||||
value => {
|
|
||||||
if (value) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('required')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value => {
|
|
||||||
if (/[^0-9]/.test(value)) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('noDigitsAllowed')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value => {
|
|
||||||
if (value?.length >= 4) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('notEnoughChars')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const passwordRules = [
|
|
||||||
value => {
|
|
||||||
if (value) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('required')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value => {
|
|
||||||
if (value?.length >= 8) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('passwordToShort')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const postalRules = [
|
|
||||||
value => {
|
|
||||||
if (/[0-9]/.test(value)) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('onlyDigitsAllowed')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value => {
|
|
||||||
if (value?.length == 5) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('notEnoughChars')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const numberRules = [
|
|
||||||
value => {
|
|
||||||
if (value) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('required')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
value => {
|
|
||||||
if (/[0-9]/.test(value)) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return feedbackStore.i18n.t('onlyDigitsAllowed')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
async function registerAccount() {
|
async function registerAccount() {
|
||||||
registerInProgress.value = true
|
registerInProgress.value = true
|
||||||
|
|
||||||
@@ -97,7 +21,10 @@ async function registerAccount() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<card-view :title="$t('account.register')">
|
<card-view
|
||||||
|
:title="$t('account.register')"
|
||||||
|
icon="mdi-account-plus"
|
||||||
|
>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
@@ -105,10 +32,12 @@ async function registerAccount() {
|
|||||||
prepend-icon="mdi-account"
|
prepend-icon="mdi-account"
|
||||||
v-model="newUser.username"
|
v-model="newUser.username"
|
||||||
clearable
|
clearable
|
||||||
:rules="stringRules"
|
:rules="getStringRules()"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('account.password')"
|
:label="$t('account.password')"
|
||||||
@@ -116,7 +45,7 @@ async function registerAccount() {
|
|||||||
type="password"
|
type="password"
|
||||||
v-model="newUser.password"
|
v-model="newUser.password"
|
||||||
clearable
|
clearable
|
||||||
:rules="passwordRules"
|
:rules="getPasswordRules()"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -124,60 +53,11 @@ async function registerAccount() {
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
:label="$t('userInfo.firstName')"
|
:label="$t('account.email')"
|
||||||
prepend-icon="mdi-card-account-details"
|
prepend-icon="mdi-mail"
|
||||||
v-model="newUser.firstName"
|
v-model="newUser.email"
|
||||||
|
:rules="getEmailRules()"
|
||||||
clearable
|
clearable
|
||||||
:rules="stringRules"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col>
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('userInfo.lastName')"
|
|
||||||
v-model="newUser.lastName"
|
|
||||||
clearable
|
|
||||||
:rules="stringRules"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('userInfo.street')"
|
|
||||||
prepend-icon="mdi-numeric"
|
|
||||||
v-model="newUser.addresses[0].street"
|
|
||||||
clearable
|
|
||||||
:rules="stringRules"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="4">
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('userInfo.houseNumber')"
|
|
||||||
v-model="newUser.addresses[0].houseNumber"
|
|
||||||
clearable
|
|
||||||
:rules="numberRules"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="4">
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('userInfo.postalCode')"
|
|
||||||
prepend-icon="mdi-city"
|
|
||||||
v-model="newUser.addresses[0].postalCode"
|
|
||||||
clearable
|
|
||||||
:rules="postalRules"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
<v-col>
|
|
||||||
<v-text-field
|
|
||||||
:label="$t('userInfo.city')"
|
|
||||||
v-model="newUser.addresses[0].city"
|
|
||||||
clearable
|
|
||||||
:rules="stringRules"
|
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import pageSetup from './pageSetup.vue';
|
import pageSetup from './pageSetup.vue';
|
||||||
import systemSetup from './systemSetup.vue';
|
import systemSetup from './systemSetup.vue';
|
||||||
import alertBanner from '@/components/alertBanner.vue';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="800">
|
<v-container max-width="800">
|
||||||
<alert-banner />
|
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<page-setup />
|
<page-setup />
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ getServerState()
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function resetDb() {
|
async function resetDb() {
|
||||||
|
serverOnline.value = ServerStateEnum.PENDING
|
||||||
|
|
||||||
await resetDatabase()
|
await resetDatabase()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result.status == 200) {
|
if (result.status == 200) {
|
||||||
feedbackStore.changeBanner(BannerStateEnum.DATABASERESETSUCCESSFUL)
|
feedbackStore.changeBanner(BannerStateEnum.DATABASERESETSUCCESSFUL)
|
||||||
|
serverOnline.value = ServerStateEnum.ONLINE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import productCard from "./productCard.vue"
|
|||||||
import productDetails from "./productDetailsDialog.vue"
|
import productDetails from "./productDetailsDialog.vue"
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { useProductStore } from "@/data/stores/productStore";
|
import { useProductStore } from "@/data/stores/productStore";
|
||||||
import alertBanner from "@/components/alertBanner.vue";
|
|
||||||
import filterNavDrawer from "./filterNavDrawer.vue";
|
import filterNavDrawer from "./filterNavDrawer.vue";
|
||||||
import { ProductModel } from '@/data/models/productModel';
|
import { ProductModel } from '@/data/models/productModel';
|
||||||
|
|
||||||
@@ -24,12 +23,6 @@ watch(() => productStore.onlyDiscounts, async () => { productStore.filterProduct
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="1000">
|
<v-container max-width="1000">
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<alert-banner />
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-row dense>
|
<v-row dense>
|
||||||
<v-col
|
<v-col
|
||||||
v-if="productStore.filteredProducts.length > 0"
|
v-if="productStore.filteredProducts.length > 0"
|
||||||
|
|||||||
169
software/src/scripts/validationRules.ts
Normal file
169
software/src/scripts/validationRules.ts
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import { useFeedbackStore } from "@/data/stores/feedbackStore"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for no numbers and more than four digits
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getStringRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/[^0-9]/.test(value)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('noDigitsAllowed')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value?.length >= 4) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('notEnoughChars')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for exact five digits length and only digits
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getPostalRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value?.length == 5) {
|
||||||
|
return true
|
||||||
|
} else if (value?.length < 5) {
|
||||||
|
return feedbackStore.i18n.t('notEnoughChars')
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('tooMuchChars')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value?.length == 5) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('notEnoughChars')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/^\d+$/.test(value)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('onlyDigitsAllowed')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for not empty and first char is a digit
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getNumberStartRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/^\d/.test(value)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('digitsAtStartNeeded')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for email format
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getEmailRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value) return true
|
||||||
|
|
||||||
|
return feedbackStore.i18n.t('emailRequired')
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/.+@.+\..+/.test(value)) return true
|
||||||
|
|
||||||
|
return feedbackStore.i18n.t('emailIsNotValid')
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for a good password
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getPasswordRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (value?.length >= 8) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('passwordToShort')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check a string for IBAN format
|
||||||
|
*
|
||||||
|
* @returns Array of rules
|
||||||
|
*/
|
||||||
|
export function getIbanRules() {
|
||||||
|
const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
|
return [
|
||||||
|
value => {
|
||||||
|
if (value) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('required')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value => {
|
||||||
|
if (/[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?!(?:[ ]?[0-9]){3})(?:[ ]?[0-9]{1,2})?/.test(value)) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return feedbackStore.i18n.t('wrongIban')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user