Merge branch 'feature/useroptions' into develop

This commit is contained in:
Tim Gröger 2020-01-27 20:19:31 +01:00
commit 4642d58a2c
31 changed files with 1347 additions and 304 deletions

10
package-lock.json generated
View File

@ -920,6 +920,16 @@
"postcss": "^7.0.0"
}
},
"@mdi/font": {
"version": "4.8.95",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-4.8.95.tgz",
"integrity": "sha512-mfEjd6kkuheZ15CBU7g/q+De9+dah/SEgVH0uZsgCJTSYa+CkXIen35aNyHoixgcEfPV4Or0NLJvyYM5CXUnbQ=="
},
"@mdi/js": {
"version": "4.8.95",
"resolved": "https://registry.npmjs.org/@mdi/js/-/js-4.8.95.tgz",
"integrity": "sha512-mKhC18fKPtSNJxpHa6tHmntnLjSUSrzOIuT4QnhlXt27MkOP5n+sQtK6Ii/R0K4fdpgLZGi+vR5o6PsDDb/iIg=="
},
"@mrmlnc/readdir-enhanced": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",

View File

@ -8,6 +8,8 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@mdi/font": "^4.8.95",
"@mdi/js": "^4.8.95",
"core-js": "^3.4.3",
"vue": "^2.6.10",
"vue-router": "^3.1.3",

View File

@ -5,23 +5,31 @@
</v-btn>
<v-toolbar-title>WU5-Dashboard</v-toolbar-title>
<v-spacer />
<v-btn icon v-if="isFinanzer" href="finanzer">
<v-icon>attach_money</v-icon>
<v-btn icon v-if="isFinanzer">
<v-icon>{{attach_money}}</v-icon>
</v-btn>
<v-btn icon v-if="isBar">
<v-icon>local_bar</v-icon>
<v-icon>{{local_bar}}</v-icon>
</v-btn>
<v-btn icon v-if="isUser">
<v-icon>person</v-icon>
<v-icon>{{person}}</v-icon>
</v-btn>
</v-app-bar>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { mdiCurrencyEur, mdiGlassCocktail, mdiAccount } from '@mdi/js'
export default {
name: 'TitleBar',
data () {
return {
attach_money: mdiCurrencyEur,
local_bar: mdiGlassCocktail,
person: mdiAccount
}
},
computed: {
...mapGetters(['isBar', 'isFinanzer', 'isUser', 'isLoggedIn'])
},

View File

@ -2,7 +2,7 @@
<v-list>
<v-list-item link to="/main/bar/geruecht">
<v-list-item-icon>
<v-icon>local_drink</v-icon>
<v-icon>{{ glass_mug_variant }}</v-icon>
</v-list-item-icon>
<v-list-item-title>
Geruecht
@ -12,8 +12,14 @@
</template>
<script>
import { mdiGlassMugVariant } from '@mdi/js'
export default {
name: 'BarNavigation'
name: 'BarNavigation',
data() {
return {
glass_mug_variant: mdiGlassMugVariant
}
}
}
</script>

View File

@ -1,9 +1,13 @@
<template>
<div>
<v-progress-linear v-if="loading && users.length !== 0" indeterminate />
<v-container>
<AddAmountSkeleton v-if="loading && users.length === 0" />
</v-container>
<div v-for="user in users" :key="users.indexOf(user)">
<div v-if="isFiltered(user)">
<v-container>
<v-card>
<v-card :loading="user.loading">
<v-list-item>
<v-list-item-title class="title"
>{{ user.firstname }} {{ user.lastname }}</v-list-item-title
@ -117,9 +121,11 @@
<script>
import { mapGetters, mapActions } from 'vuex'
import AddAmountSkeleton from '../user/Skeleton/AddAmountSkeleton'
export default {
name: 'CreditLists',
components: { AddAmountSkeleton },
props: {},
data() {
return {
@ -151,7 +157,8 @@ export default {
computed: {
...mapGetters({
users: 'barUsers/users',
filter: 'barUsers/filter'
filter: 'barUsers/filter',
loading: 'barUsers/usersLoading'
})
}
}

View File

@ -11,10 +11,14 @@
placeholder="Suche Person"
:items="allUsers"
item-text="fullName"
prepend-inner-icon="search"
full-width
:loading="loading"
:search-input.sync="filter"
/>
>
<template v-slot:prepend-inner>
<v-icon>{{search_person}}</v-icon>
</template>
</v-autocomplete>
<v-btn text @click="addUser">Hinzufügen</v-btn>
</v-toolbar-items>
</v-toolbar>
@ -23,6 +27,7 @@
<script>
import { mapGetters, mapActions } from 'vuex'
import { mdiAccountSearch } from '@mdi/js'
export default {
name: 'SearchBar',
@ -30,7 +35,8 @@ export default {
data() {
return {
user: null,
filter: ''
filter: '',
search_person: mdiAccountSearch
}
},
created() {
@ -48,7 +54,10 @@ export default {
}
},
computed: {
...mapGetters({ allUsers: 'barUsers/allUsers' })
...mapGetters({
allUsers: 'barUsers/allUsers',
loading: 'barUsers/allUsersLoading'
})
},
watch: {
filter(val) {

View File

@ -1,23 +1,17 @@
<template>
<div>
<v-list>
<v-list-item
class="title"
link
to="/main/finanzer/overview"
>
<v-list-item class="title" link to="/main/finanzer/overview">
<v-list-item-icon>
<v-icon>home</v-icon>
<v-icon>{{home}}</v-icon>
</v-list-item-icon>
<v-list-item-title>Gesamtübersicht</v-list-item-title>
</v-list-item>
<v-list-item link to="/main/finanzer/servicemanagement">
<v-list-item-icon>
<v-icon>work</v-icon>
<v-icon>{{work}}</v-icon>
</v-list-item-icon>
<v-list-item-title>
Dienstverwaltung
</v-list-item-title>
<v-list-item-title>Dienstverwaltung</v-list-item-title>
</v-list-item>
</v-list>
<v-divider />
@ -28,27 +22,38 @@
link
>
<v-list-item-title
>{{ user.lastname }}, {{ user.firstname }}
</v-list-item-title>
>{{ user.lastname }}, {{ user.firstname }}</v-list-item-title
>
</v-list-item>
</div>
<v-list-item>
<v-progress-circular indeterminate color="grey" v-if="loading" />
</v-list-item>
</v-list>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import {mdiHome, mdiBriefcase} from '@mdi/js'
export default {
name: 'FinanzerNavigation',
data () {
return {
home: mdiHome,
work: mdiBriefcase
}
},
methods: {
...mapActions({
addUser: 'finanzerUsers/addUser',
addUser: 'finanzerUsers/addUser'
})
},
computed: {
...mapGetters({
users: 'finanzerUsers/users',
allUsers: 'finanzerUsers/allUsers'
allUsers: 'finanzerUsers/allUsers',
loading: 'finanzerUsers/usersLoading'
})
}
}

View File

@ -5,13 +5,13 @@
<v-spacer />
<v-toolbar-items>
<v-btn text icon @click="countYear(false)">
<v-icon>keyboard_arrow_left</v-icon>
<v-icon>{{keyboard_arrow_left}}</v-icon>
</v-btn>
<v-list-item>
<v-list-item-title class="title">{{ year }}</v-list-item-title>
</v-list-item>
<v-btn text icon @click="countYear(true)" :disabled="isActualYear">
<v-icon>keyboard_arrow_right</v-icon>
<v-icon>{{keyboard_arrow_right}}</v-icon>
</v-btn>
</v-toolbar-items>
<v-spacer />
@ -25,10 +25,14 @@
placeholder="Suche Person"
:items="allUsers"
item-text="fullName"
prepend-inner-icon="search"
full-width
:loading="allUsersLoading"
:search-input.sync="filter"
/>
>
<template v-slot:prepend-inner>
<v-icon>{{search_person}}</v-icon>
</template>
</v-autocomplete>
<v-btn
text
@click="addToUser(user)"
@ -62,10 +66,13 @@
</v-expand-transition>
</v-card>
</v-expand-transition>
<v-progress-linear v-if="loading && users.length !== 0" indeterminate />
<TableSkeleton v-if="loading && users.length === 0" />
<div v-for="user in users" :key="users.indexOf(user)">
<v-card
v-if="user.creditList[year] && isFiltered(user)"
style="margin-top: 3px"
:loading="user.loading"
>
<v-card-title>{{ user.lastname }}, {{ user.firstname }}</v-card-title>
<Table v-bind:user="user" v-bind:year="year" />
@ -206,12 +213,17 @@
<script>
import Table from './Table'
import { mapGetters, mapActions } from 'vuex'
import TableSkeleton from './Skeleton/TableSkeleton'
import {mdiChevronLeft, mdiChevronRight, mdiAccountSearch} from '@mdi/js'
export default {
name: 'Overview',
components: { Table },
components: { TableSkeleton, Table },
props: {},
data() {
return {
keyboard_arrow_left: mdiChevronLeft,
keyboard_arrow_right: mdiChevronRight,
search_person: mdiAccountSearch,
errorExpand: false,
filter: '',
@ -369,7 +381,9 @@ export default {
errorMails: 'finanzerUsers/errorMails',
year: 'finanzerUsers/year',
years: 'finanzerUsers/years',
months: 'finanzerUsers/months'
months: 'finanzerUsers/months',
loading: 'finanzerUsers/usersLoading',
allUsersLoading: 'finanzerUsers/allUsersLoading'
})
}
}

View File

@ -0,0 +1,60 @@
<template>
<div>
<v-card style="margin-top: 3px">
<v-card-title>
<v-skeleton-loader type="heading" />
</v-card-title>
<v-container>
<v-skeleton-loader type="table-thead"/>
<v-skeleton-loader type="table-row-divider@3"/>
</v-container>
<v-container fluid>
<v-row align="start" align-content="start">
<v-col>
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
<v-row>
<v-col>
<v-skeleton-loader type="chip"/>
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
</v-col>
<v-col align-self="center">
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
<v-card outlined>
<v-row>
<v-card-title>
<v-skeleton-loader style="margin: 3px; margin-left: 10px" type="chip"/>
</v-card-title>
</v-row>
</v-card>
</v-col>
</v-row>
</v-container>
</v-card>
</div>
</template>
<script>
export default {
name: 'TableSkeleton'
}
</script>
<style scoped></style>

View File

@ -0,0 +1,82 @@
<template>
<div>
<v-toolbar tile>
<v-toolbar-title>
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
</v-toolbar-title>
<v-spacer />
<v-toolbar-items>
<v-skeleton-loader type="button" />
</v-toolbar-items>
</v-toolbar>
<v-card style="margin-top: 3px;">
<v-card-title><v-skeleton-loader type="heading"/></v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
</v-row>
<v-divider style="margin-bottom: 15px;" />
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
<v-row>
<v-skeleton-loader type="button" />
</v-row>
</v-form>
</v-card-text>
</v-card>
<v-card style="margin-top: 3px;">
<v-card-title><v-skeleton-loader type="chip"/></v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
</v-form>
<v-skeleton-loader type="button" />
</v-card-text>
</v-card>
</div>
</template>
<script>
export default {
name: 'UserSkeleton'
}
</script>
<style scoped></style>

View File

@ -1,202 +1,207 @@
<template>
<v-content v-if="activeUser">
<v-toolbar tile>
<v-toolbar-title
>{{ activeUser.lastname }}, {{ activeUser.firstname }}</v-toolbar-title
>
<v-spacer />
<v-toolbar-items>
<v-btn @click="sendMail({ username: activeUser.username })" text
>Email senden</v-btn
<div>
<v-content v-if="loading" >
<UserSkeleton />
</v-content>
<v-content v-if="activeUser">
<v-toolbar tile>
<v-toolbar-title
>{{ activeUser.lastname }},
{{ activeUser.firstname }}</v-toolbar-title
>
</v-toolbar-items>
</v-toolbar>
<v-expand-transition>
<v-card style="margin-top: 3px" v-show="errorMail">
<v-alert dense :type="computeError(errorMail)">{{
errorMessage(errorMail)
}}</v-alert>
</v-card>
</v-expand-transition>
<v-card style="margin-top: 3px;">
<v-card-title>Konfiguration</v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-label>Status:</v-label>
</v-col>
<v-col>
<v-chip
outlined
:text-color="getLockedColor(activeUser.locked)"
>{{ activeUser.locked ? 'Gesperrt' : 'nicht Gesperrt' }}</v-chip
>
</v-col>
<v-col>
<v-btn
@click="
doLock({ user: activeUser, locked: !activeUser.locked })
"
>{{ activeUser.locked ? 'Entperren' : 'Sperren' }}</v-btn
>
</v-col>
</v-row>
<v-divider style="margin-bottom: 15px;" />
<v-row>
<v-col>
<v-text-field
:rules="[isNumber]"
label="Betrag des Sperrlimits in € (EURO)"
v-model="limit"
></v-text-field>
</v-col>
<v-col>
<v-select
return-object
v-model="autoLock"
label="Automatische Sperre"
:items="[
{ value: true, text: 'Aktiviert' },
{ value: false, text: 'Deaktiviert' }
]"
item-text="text"
item-value="value"
/>
</v-col>
</v-row>
<v-row>
<v-btn
block
@click="
saveConfig({
user: activeUser,
limit: limit,
autoLock: autoLock.value
})
"
>Speichern</v-btn
>
</v-row>
</v-form>
</v-card-text>
</v-card>
<v-card style="margin-top: 3px;">
<v-card-title>Geld transferieren</v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-text-field
:rules="[isNumber]"
label="Betrag"
v-model="amount"
></v-text-field>
</v-col>
<v-col>
<v-select
return-object
v-model="type"
label="Typ"
:items="[
{ value: 'amount', text: 'Schulden' },
{ value: 'credit', text: 'Guthaben' }
]"
item-text="text"
item-value="value"
></v-select>
</v-col>
</v-row>
<v-row>
<v-col>
<v-select
return-object
v-model="selectedYear"
label="Jahr"
:items="selectYears"
item-text="text"
item-value="value"
></v-select>
</v-col>
<v-col>
<v-select
return-object
v-model="selectedMonth"
label="Monat"
:items="months"
item-text="text"
item-value="value"
></v-select>
</v-col>
</v-row>
</v-form>
<v-btn block @click="add">Hinzufügen</v-btn>
</v-card-text>
</v-card>
<div v-for="year in years" :key="years.indexOf(year)">
<v-spacer />
<v-toolbar-items>
<v-btn @click="sendMail({ username: activeUser.username })" text
>Email senden</v-btn
>
</v-toolbar-items>
</v-toolbar>
<v-progress-linear v-if="activeUser.loading" indeterminate />
<v-expand-transition>
<v-card style="margin-top: 3px" v-show="errorMail">
<v-alert dense :type="computeError(errorMail)">
{{ errorMessage(errorMail) }}
</v-alert>
</v-card>
</v-expand-transition>
<v-card style="margin-top: 3px;">
<v-card-title>{{ year }}</v-card-title>
<Table v-bind:user="activeUser" v-bind:year="year" />
<v-container fluid>
<v-col>
<v-card-title>Konfiguration</v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-label>Vorjahr:</v-label>
<v-label>Status:</v-label>
</v-col>
<v-col>
<v-chip
outlined
:text-color="
getLastColor(activeUser.creditList[year][1].last)
"
>{{
(activeUser.creditList[year][1].last / 100).toFixed(2)
}}</v-chip
>
</v-col>
<v-col>
<v-label>Gesamt:</v-label>
</v-col>
<v-col>
<v-chip
outlined
x-large
:text-color="
getLastColor(
getAllSum(
activeUser.creditList[year][2].sum,
activeUser.creditList[year][1].last
)
)
"
>
{{
(
getAllSum(
activeUser.creditList[year][2].sum,
activeUser.creditList[year][1].last
) / 100
).toFixed(2)
}}
<v-chip outlined :text-color="getLockedColor(activeUser.locked)"
>{{ activeUser.locked ? 'Gesperrt' : 'nicht Gesperrt' }}
</v-chip>
</v-col>
<v-col>
<v-btn
@click="
doLock({ user: activeUser, locked: !activeUser.locked })
"
>{{ activeUser.locked ? 'Entperren' : 'Sperren' }}
</v-btn>
</v-col>
</v-row>
</v-col>
</v-container>
<v-divider style="margin-bottom: 15px;" />
<v-row>
<v-col>
<v-text-field
:rules="[isNumber]"
label="Betrag des Sperrlimits in € (EURO)"
v-model="limit"
></v-text-field>
</v-col>
<v-col>
<v-select
return-object
v-model="autoLock"
label="Automatische Sperre"
:items="[
{ value: true, text: 'Aktiviert' },
{ value: false, text: 'Deaktiviert' }
]"
item-text="text"
item-value="value"
/>
</v-col>
</v-row>
<v-row>
<v-btn
block
@click="
saveConfig({
user: activeUser,
limit: limit,
autoLock: autoLock.value
})
"
>Speichern
</v-btn>
</v-row>
</v-form>
</v-card-text>
</v-card>
</div>
</v-content>
<v-card style="margin-top: 3px;">
<v-card-title>Geld transferieren</v-card-title>
<v-card-text>
<v-form style="margin-left: 15px; margin-right: 15px">
<v-row>
<v-col>
<v-text-field
:rules="[isNumber]"
label="Betrag"
v-model="amount"
></v-text-field>
</v-col>
<v-col>
<v-select
return-object
v-model="type"
label="Typ"
:items="[
{ value: 'amount', text: 'Schulden' },
{ value: 'credit', text: 'Guthaben' }
]"
item-text="text"
item-value="value"
></v-select>
</v-col>
</v-row>
<v-row>
<v-col>
<v-select
return-object
v-model="selectedYear"
label="Jahr"
:items="selectYears"
item-text="text"
item-value="value"
></v-select>
</v-col>
<v-col>
<v-select
return-object
v-model="selectedMonth"
label="Monat"
:items="months"
item-text="text"
item-value="value"
></v-select>
</v-col>
</v-row>
</v-form>
<v-btn block @click="add">Hinzufügen</v-btn>
</v-card-text>
</v-card>
<div v-for="year in years" :key="years.indexOf(year)">
<v-card style="margin-top: 3px;">
<v-card-title>{{ year }}</v-card-title>
<Table v-bind:user="activeUser" v-bind:year="year" />
<v-container fluid>
<v-col>
<v-row>
<v-col>
<v-label>Vorjahr:</v-label>
</v-col>
<v-col>
<v-chip
outlined
:text-color="
getLastColor(activeUser.creditList[year][1].last)
"
>
{{ (activeUser.creditList[year][1].last / 100).toFixed(2) }}
</v-chip>
</v-col>
<v-col>
<v-label>Gesamt:</v-label>
</v-col>
<v-col>
<v-chip
outlined
x-large
:text-color="
getLastColor(
getAllSum(
activeUser.creditList[year][2].sum,
activeUser.creditList[year][1].last
)
)
"
>
{{
(
getAllSum(
activeUser.creditList[year][2].sum,
activeUser.creditList[year][1].last
) / 100
).toFixed(2)
}}
</v-chip>
</v-col>
</v-row>
</v-col>
</v-container>
</v-card>
</div>
</v-content>
</div>
</template>
<script>
import Table from './Table'
import { mapGetters, mapActions } from 'vuex'
import UserSkeleton from "./Skeleton/UserSkeleton";
export default {
name: 'User',
props: {
id: String
},
components: { Table },
components: {UserSkeleton, Table },
data() {
return {
isNumber: value => !isNaN(value) || 'Betrag muss eine Zahl sein.',
@ -336,11 +341,13 @@ export default {
activeUser: 'finanzerUsers/activeUser',
errorMail: 'finanzerUsers/errorMail',
months: 'finanzerUsers/months',
selectYears: 'finanzerUsers/selectYears'
selectYears: 'finanzerUsers/selectYears',
loading: 'finanzerUsers/addUserLoading'
})
},
watch: {
activeUser(newVal) {
// eslint-disable-next-line no-console
console.log(newVal)
this.limit = (newVal.limit / 100).toFixed(2)
this.autoLock = {
@ -349,6 +356,7 @@ export default {
}
},
id(newVal) {
// eslint-disable-next-line no-console
console.log(newVal)
this.setActiveUser(newVal)
}

View File

@ -1,6 +1,7 @@
<template>
<v-container v-if="user">
<v-card>
<v-container >
<AddAmountSkeleton v-if="loading" />
<v-card v-if="!loading" :loading="addLoading">
<v-list-item>
<v-list-item-title class="title"
>{{ user.firstname }} {{ user.lastname }}</v-list-item-title
@ -99,8 +100,10 @@
<script>
import {mapGetters, mapActions} from 'vuex'
import AddAmountSkeleton from './Skeleton/AddAmountSkeleton'
export default {
name: 'AddAmount',
components: { AddAmountSkeleton },
data() {
return {
color: 'green accent-4'
@ -123,7 +126,9 @@ export default {
computed: {
...mapGetters({
user: 'user/user',
year: 'user/year'
year: 'user/year',
loading: 'user/loading',
addLoading: 'user/addLoading'
}),
}
}

View File

@ -0,0 +1,210 @@
<template>
<div>
<v-card v-if="user" :loading="loading" style="margin-top: 3px">
<v-card-title>{{ user.firstname }} {{ user.lastname }}</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12" sm="6">
<v-text-field
outlined
label="Vornamen"
:placeholder="user.firstname"
v-model="firstname"
readonly
/>
</v-col>
<v-col cols="12" sm="6">
<v-text-field
outlined
label="Nachname"
:placeholder="user.lastname"
v-model="lastname"
readonly
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" sm="6">
<v-text-field
outlined
label="Benutzername"
:placeholder="user.username"
v-model="username"
readonly
></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-text-field
ref="mail"
outlined
label="E-Mail"
:placeholder="user.mail"
v-model="mail"
readonly
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col cols="12" sm="6">
<v-text-field
outlined
label="Password"
type="password"
v-model="password"
/>
</v-col>
<v-col cols="12" sm="6">
<v-text-field
ref="password"
outlined
label="Password bestätigen"
type="password"
:disabled="!password"
:rules="[equal_password]"
/>
</v-col>
</v-row>
<v-divider />
<v-row>
<v-col cols="12" sm="4">
<v-text-field
outlined
label="Sperrlimit"
readonly
:value="(user.limit / 100).toFixed(2).toString() + '€'"
/>
</v-col>
<v-col cols="12" sm="4">
<v-combobox
outlined
label="Sperrstatus"
v-model="lock"
append-icon
readonly
>
<template v-slot:selection="data">
<v-chip :color="lockColor">
{{ data.item }}
</v-chip>
</template>
</v-combobox>
</v-col>
<v-col cols="12" sm="4">
<v-combobox
outlined
label="Autosperre"
v-model="autoLock"
readonly
append-icon
>
<template v-slot:selection="data">
<v-chip :color="autoLockColor">
{{ data.item }}
</v-chip>
</template>
</v-combobox>
</v-col>
</v-row>
<v-row>
<v-col>
<v-combobox
outlined
multiple
label="Gruppen"
readonly
v-model="user.group"
append-icon
>
<template v-slot:selection="data">
<v-icon>{{
data.item === 'user'
? person
: data.item === 'bar'
? bar
: data.item === 'moneymaster'
? finanzer
: false
}}</v-icon>
</template>
</v-combobox>
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="save">Save</v-btn>
</v-card-actions>
<v-expand-transition>
<v-alert type="error" v-if="error">{{error}}</v-alert>
</v-expand-transition>
</v-card>
</div>
</template>
<script>
import { mdiAccount, mdiGlassCocktail, mdiCurrencyEur } from '@mdi/js'
import { mapGetters, mapActions } from 'vuex'
export default {
name: 'Config',
data() {
return {
person: mdiAccount,
bar: mdiGlassCocktail,
finanzer: mdiCurrencyEur,
username: null,
mail: null,
firstname: null,
lastname: null,
password: null,
equal_password: value =>
this.password === value || 'Passwörter sind nicht identisch.',
email: value => {
if(value.length > 0) {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return pattern.test(value) || 'keine gültige E-Mail';
}
return true
}
}
},
methods: {
...mapActions({
saveConfig: 'user/saveConfig'
}),
save() {
let user = {}
if (this.firstname) user.firstname = this.firstname
if (this.lastname) user.lastname = this.lastname
if (this.username) user.username = this.username
if (this.$refs.mail.validate()) {
if (this.mail) user.mail = this.mail
}
if (this.$refs.password.validate()) {
if (this.password) user.password = this.password
}
this.saveConfig({oldUsername: user.username, ...user})
}
},
computed: {
...mapGetters({
user: 'user/user',
error: 'user/error',
loading: 'user/loading'
}),
lock() {
return this.user.locked ? 'gesperrt' : 'nicht gesperrt'
},
lockColor() {
return this.user.locked ? 'red' : 'green'
},
autoLock() {
return this.user.autoLock ? 'aktiviert' : 'deaktiviert'
},
autoLockColor() {
return this.user.autoLock ? 'green' : 'red'
}
}
}
</script>
<style scoped></style>

View File

@ -7,12 +7,17 @@
<v-text-field
v-model="filter"
style="margin-top: 3px"
append-icon="search"
outlined
type="number"
:rules="[isNumber]"
></v-text-field>
>
<template v-slot:append>
<v-icon>{{magnify}}</v-icon>
</template>
</v-text-field>
</v-toolbar-items>
</v-toolbar>
<CreditOverviewSkeleton v-if="loading" />
<div v-for="year in years" :key="years.indexOf(year)">
<v-card style="margin-top: 3px" v-if="isFiltered(year)">
<v-card-title>{{ year }}</v-card-title>
@ -67,13 +72,16 @@
<script>
import { mapGetters } from 'vuex'
import Table from '../finanzer/Table'
import CreditOverviewSkeleton from './Skeleton/CreditOverviewSkeleton'
import { mdiMagnify } from '@mdi/js'
export default {
name: 'CreditOverview',
components: { Table },
components: { CreditOverviewSkeleton, Table },
data() {
return {
isNumber: value => Number.isInteger(parseInt(value === '' ? 0 : value)) || "Muss eine Zahl sein.",
filter: ''
filter: '',
magnify: mdiMagnify
}
},
methods: {
@ -89,7 +97,8 @@ export default {
},
computed: {
...mapGetters({
user: 'user/user'
user: 'user/user',
loading: 'user/loading'
}),
years() {
let years = []

View File

@ -0,0 +1,90 @@
<template>
<div>
<v-toolbar>
<v-toolbar-title>
Dienstübersicht
</v-toolbar-title>
<v-spacer />
<v-toolbar-items>
<v-btn text icon @click="changeMonth(-1)">
<v-icon>{{ keyboard_arrow_left }}</v-icon>
</v-btn>
<v-list-item>
<v-list-item-title class="title"
>{{ date.getDate() }}.{{ date.getMonth() + 1 }}.{{
date.getFullYear()
}}
bis {{ toDate.getDate() }}.{{ toDate.getMonth() + 1 }}.{{
toDate.getFullYear()
}}
</v-list-item-title>
</v-list-item>
<v-btn text icon @click="changeMonth(1)">
<v-icon>{{ keyboard_arrow_right }}</v-icon>
</v-btn>
</v-toolbar-items>
<v-spacer />
</v-toolbar>
<v-progress-linear indeterminate v-if="loading" />
<div v-for="day in days" :key="days.indexOf(day)">
<Day v-bind:day="day" style="margin-top: 3px"></Day>
</div>
</div>
</template>
<script>
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js'
import { mapGetters, mapActions } from 'vuex'
import Day from '@/components/user/Jobs/Day'
export default {
name: 'Jobs',
components: { Day },
data() {
return {
keyboard_arrow_left: mdiChevronLeft,
keyboard_arrow_right: mdiChevronRight,
date: new Date()
}
},
created() {
this.createDays(this.date)
},
methods: {
...mapActions({
createDays: 'user/createDays'
}),
changeMonth(value) {
if (value === -1) {
this.date = new Date(
this.date.getFullYear(),
this.date.getMonth(),
this.date.getDate() - 1
)
} else {
this.date = new Date(
this.date.getFullYear(),
this.date.getMonth(),
this.date.getDate() + 1
)
}
this.createDays(this.date)
},
test(day) {
let index = this.days.indexOf(day)
console.log(index, index % 3)
return true
}
},
computed: {
...mapGetters({
days: 'user/days',
loading: 'user/loading'
}),
toDate() {
return new Date(new Date().setDate(this.date.getDate() + 10))
}
}
}
</script>
<style scoped></style>

View File

@ -0,0 +1,74 @@
<template>
<v-card v-if="day.job">
<v-card-title
>{{ daysArray[day.date.getDay()] }} den {{ day.date.getDate() }}
{{ monthArray[day.date.getMonth()] }}
{{ day.date.getFullYear() }}
</v-card-title>
<v-card-text v-if="day.workers.length !== 0">
Du hast Dienst mit:
<v-chip
style="margin: 3px"
v-for="person in day.workers"
:key="day.workers.indexOf(person)"
>{{ person.user.firstname }}
{{ person.user.lastname }}
</v-chip>
</v-card-text>
<v-card-text v-else>
Du hast alleine Dienst!
</v-card-text>
</v-card>
</template>
<script>
import { mapActions } from 'vuex'
export default {
name: 'Day',
props: {
day: Object
},
data() {
return {
monthArray: [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember'
],
daysArray: [
'Sonntag',
'Montag',
'Dienstag',
'Mittwoch',
'Donnerstag',
'Freitag',
'Samstag'
]
}
},
created() {
this.updateDay({ date: this.day.date })
},
methods: {
...mapActions({
updateDay: 'user/updateDay'
})
},
watch: {
day() {
this.updateDay({ date: this.day.date })
}
}
}
</script>
<style scoped></style>

View File

@ -0,0 +1,50 @@
<template>
<v-card>
<v-card-title>
<v-skeleton-loader type="heading" />
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="10">
<v-row>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
</v-row>
<v-row>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
<v-col>
<v-skeleton-loader type="button" />
</v-col>
</v-row>
</v-col>
<v-col align-self="center">
<v-row>
<v-list-item>
<v-skeleton-loader type="chip" />
</v-list-item>
</v-row>
</v-col>
</v-row>
</v-card-text>
</v-card>
</template>
<script>
export default {
name: 'AddAmountSkeleton'
}
</script>
<style scoped></style>

View File

@ -0,0 +1,35 @@
<template>
<v-card style="margin-top: 3px">
<v-card-title><v-skeleton-loader type="heading"/></v-card-title>
<v-container>
<v-skeleton-loader type="table-thead" />
<v-skeleton-loader type="table-row-divider@3" />
</v-container>
<v-container fluid>
<v-col>
<v-row>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
<v-col>
<v-skeleton-loader type="chip" />
</v-col>
</v-row>
</v-col>
</v-container>
</v-card>
</template>
<script>
export default {
name: 'CreditOverviewSkeleton'
}
</script>
<style scoped></style>

View File

@ -2,7 +2,7 @@
<v-list>
<v-list-item link to="/main/user/add">
<v-list-item-icon>
<v-icon>home</v-icon>
<v-icon>{{account}}</v-icon>
</v-list-item-icon>
<v-list-item-title>
Home
@ -10,16 +10,39 @@
</v-list-item>
<v-list-item link to="/main/user/overview">
<v-list-item-icon>
<v-icon>account_balance</v-icon>
<v-icon>{{bank}}</v-icon>
</v-list-item-icon>
<v-list-item-title>Finanzübersicht</v-list-item-title>
</v-list-item>
<v-list-item link to="/main/user/jobs">
<v-list-item-icon>
<v-icon>
{{briefcase}}
</v-icon>
</v-list-item-icon>
<v-list-item-title>Dienstübersicht</v-list-item-title>
</v-list-item>
<v-list-item link to="/main/user/config">
<v-list-item-icon>
<v-icon>{{account_card_details}}</v-icon>
</v-list-item-icon>
<v-list-item-title>Einstellung</v-list-item-title>
</v-list-item>
</v-list>
</template>
<script>
import {mdiAccountCardDetails, mdiHome, mdiBank, mdiBriefcase } from '@mdi/js'
export default {
name: 'UserNavigation'
name: 'UserNavigation',
data () {
return {
account_card_details: mdiAccountCardDetails,
account: mdiHome,
bank: mdiBank,
briefcase: mdiBriefcase
}
}
}
</script>

View File

@ -8,7 +8,7 @@
<v-spacer />
<v-toolbar-items>
<v-btn text icon @click="changeMonth(-1)">
<v-icon>keyboard_arrow_left</v-icon>
<v-icon>{{keyboard_arrow_left}}</v-icon>
</v-btn>
<v-list-item>
<v-list-item-title class="title"
@ -17,7 +17,7 @@
>
</v-list-item>
<v-btn text icon @click="changeMonth(1)">
<v-icon>keyboard_arrow_right</v-icon>
<v-icon>{{keyboard_arrow_right}}</v-icon>
</v-btn>
</v-toolbar-items>
<v-spacer />
@ -47,12 +47,15 @@
<script>
import { mapGetters, mapActions } from 'vuex'
import {mdiChevronLeft, mdiChevronRight} from '@mdi/js'
import Day from './ServiceManagementComponents/Day'
export default {
name: 'ServiceManagement',
components: { Day },
data() {
return {
keyboard_arrow_left: mdiChevronLeft,
keyboard_arrow_right: mdiChevronRight,
id: 0,
date: new Date(),
monthArray: [
@ -91,7 +94,7 @@ export default {
},
computed: {
...mapGetters({
month: 'sm/month'
month: 'sm/month',
})
}
}

View File

@ -1,43 +1,59 @@
<template>
<div v-if="day">
<v-card :color="color(day)" max-width="300px" min-width="300px">
<v-card :color="color(day)" max-width="250px" min-width="250px">
<v-card-title v-if="day.date" class="subtitle-1 font-weight-bold">
{{ day.name }} den {{ day.date.getDate() }}.{{
day.date.getMonth() + 1
}}.{{ day.date.getFullYear() }}
</v-card-title>
<v-card-text>
<v-autocomplete
chips
return-object
multiple
v-model="day.worker"
:items="allUsers"
item-text="fullName"
label="Dienste"
prepend-inner-icon="group_add"
filled
color="green"
>
<template v-slot:selection="data">
<v-chip
v-bind="data.attrs"
:input-value="data.selected"
close
@click="data.select"
@click:close="remove(data.item)"
<v-expand-transition>
<v-row align="center" justify="center" v-if="day.loading">
<v-progress-circular indeterminate color="grey" />
</v-row>
</v-expand-transition>
<v-expand-transition>
<div v-show="!day.loading">
<v-autocomplete
chips
return-object
multiple
v-model="day.worker"
:items="allUsers"
item-text="fullName"
label="Dienste"
filled
color="green"
@input="searchInput=null"
:search-input.sync="searchInput"
@blur="focused=false"
@focus="focused=true"
>
{{ data.item.firstname }} {{ data.item.lastname }}
</v-chip>
</template>
<template v-slot:item="data">
<v-list-item-content>
<v-list-item-title>
{{ data.item.firstname }} {{ data.item.lastname }}
</v-list-item-title>
</v-list-item-content>
</template>
</v-autocomplete>
<template v-slot:prepend-inner>
<v-icon>{{account_add}}</v-icon>
</template>
<template v-slot:selection="data">
<v-chip
v-bind="data.attrs"
:input-value="data.selected"
close
@click="data.select"
@click:close="remove(data.item)"
>
{{ data.item.firstname }} {{ data.item.lastname }}
</v-chip>
</template>
<template v-slot:item="data">
<v-list-item-content>
<v-list-item-title>
{{ data.item.firstname }} {{ data.item.lastname }}
</v-list-item-title>
</v-list-item-content>
</template>
</v-autocomplete>
</div>
</v-expand-transition>
</v-card-text>
</v-card>
</div>
@ -45,22 +61,33 @@
<script>
import { mapGetters, mapActions } from 'vuex'
import {mdiAccountPlus} from '@mdi/js'
export default {
name: 'Day',
props: {
day: Object
},
data() {
return {}
return {
account_add: mdiAccountPlus,
searchInput: null,
focused: false
}
},
created() {
this.getUser({date: this.day.date.getTime()/1000})
this.setLoading(this.day.date)
this.getUser({
date: this.day.date.getTime() / 1000,
startdatetime: this.day.date
})
},
methods: {
...mapActions({
addUser: 'sm/addUser',
getUser: 'sm/getUser',
deleteUser: 'sm/deleteUser'
deleteUser: 'sm/deleteUser',
setLoading: 'sm/setDayLoading',
setNotLoading: 'sm/setDayNotLoading'
}),
// eslint-disable-next-line no-unused-vars
remove(deletedUser) {
@ -69,7 +96,14 @@ export default {
})
const index = this.day.worker.indexOf(obj)
if (index >= 0) this.day.worker.splice(index, 1)
this.deleteUser({startdatetime: this.day.date, date: this.day.date.getTime()/1000, user: deletedUser})
this.deleteUser({
startdatetime: this.day.date,
date: this.day.date.getTime() / 1000,
user: deletedUser
})
},
test(event) {
console.log('blur', event)
},
color: day => {
if (day) {
@ -85,11 +119,12 @@ export default {
} else {
return 'grey lighten-4'
}
}
},
},
computed: {
...mapGetters({
allUsers: 'sm/allUsers'
allUsers: 'sm/allUsers',
disabled: 'sm/disabled'
}),
worker() {
return this.day.worker
@ -97,22 +132,39 @@ export default {
},
watch: {
worker(newValue, oldValue) {
if (oldValue !== newValue) {
if (oldValue !== newValue && this.focused) {
let addedUser = null
for (let user in newValue) {
if (!oldValue.includes(newValue[user])) {
addedUser = newValue[user]
this.addUser({date: this.day.date.getTime()/1000, user: addedUser})
this.addUser({
date: this.day.date.getTime() / 1000,
user: addedUser
})
}
}
let deletedUser = null
for (let user in oldValue) {
if (!newValue.includes(oldValue[user])) {
deletedUser = oldValue[user]
this.deleteUser({startdatetime: this.day.date, date: this.day.date.getTime()/1000, user: deletedUser})
console.log("deleteUser", deletedUser, this.day.date)
this.deleteUser({
startdatetime: this.day.date,
date: this.day.date.getTime() / 1000,
user: deletedUser
})
}
}
}
},
day() {
this.getUser({
date: this.day.date.getTime() / 1000,
startdatetime: this.day.date
})
},
focused(newVal, oldValue) {
console.log(newVal, oldValue)
}
}
}

View File

@ -1,5 +1,6 @@
//const main = 'https://192.168.5.128:5000/'
const main = 'https://localhost:5000/'
const main = 'http://localhost:5000/'
//const main = 'http://192.168.5.118:5000/'
//const main = 'https://groeger-clan.duckdns.org:5000/'
const url = {
@ -25,6 +26,10 @@ const url = {
deleteUser: main + 'sm/deleteUser',
getUser: main + 'sm/getUser'
}
},
user: {
config: main + 'user/saveConfig',
job: main + 'user/job'
}
}

View File

@ -1,11 +1,10 @@
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
import 'material-design-icons-iconfont'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'md'
iconfont: 'mdiSvg'
}
})

View File

@ -15,6 +15,8 @@ import FinanzerNavigation from '../components/finanzer/FinanzerNavigation'
import Overview from '../components/finanzer/Overview'
import User from '../components/finanzer/User'
import ServiceManagement from '../components/vorstand/ServiceManagement'
import Config from "@/components/user/Config";
import Jobs from "@/components/user/Jobs";
Vue.use(VueRouter)
@ -43,6 +45,16 @@ const routes = [
path: 'overview',
name: 'userOverview',
component: CreditOverview
},
{
path: 'config',
name: 'userConfig',
component: Config
},
{
path: 'jobs',
name: 'userJobs',
component: Jobs
}
]
},
@ -97,7 +109,6 @@ const router = new VueRouter({
router.beforeEach((to, from, next) => {
store.dispatch('fetchAccessToken')
console.log('fullPath', to.fullPath)
if (to.fullPath.includes('/main')) {
if (to.fullPath.includes('/main/finanzer')) {
if (!store.state.login.user.group.includes('moneymaster')) {

View File

@ -4,7 +4,9 @@ import url from '@/plugins/routes'
const state = {
users: [],
allUsers: [],
filter: ''
filter: '',
usersLoading: false,
allUsersLoading: false
}
const mutations = {
@ -36,12 +38,21 @@ const mutations = {
lastname: users[user].lastname,
locked: users[user].locked,
amount: users[user].amount,
type: users[user].type
type: users[user].type,
loading: false
})
}
}
mutations.sortUsers(state)
},
updateUser: (state, data) => {
let index = state.users.indexOf(
state.users.find(a => {
return a.username === data.username
})
)
if (data.loading !== undefined) state.users[index].loading = data.loading
},
sortUsers: state => {
state.users = state.users.sort((a, b) => {
if (a.lastname > b.lastname) return 1
@ -53,12 +64,19 @@ const mutations = {
},
setFilter: (state, filter) => {
state.filter = filter
},
setUsersLoading: (state, value) => {
state.usersLoading = value
},
setAllUsersLoading: (state, value) => {
state.allUsersLoading = value
}
}
const actions = {
// eslint-disable-next-line no-unused-vars
async getUsers({ commit, rootState, dispatch }) {
commit('setUsersLoading', true)
try {
const response = await axios.get(url.bar, {
headers: { Token: rootState.login.user.accessToken }
@ -68,8 +86,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('setUsersLoading', false)
},
async addAmount({ commit, rootState, dispatch }, data) {
commit('updateUser', { username: data.username, loading: true })
try {
const response = await axios.post(
url.barAddAmount,
@ -81,8 +101,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('updateUser', { username: data.username, loading: false })
},
async addCreditList({ commit, rootState, dispatch }, data) {
commit('updateUser', { username: data.username, loading: true })
try {
const response = await axios.post(
url.barGetUser,
@ -94,8 +116,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('updateUser', { username: data.username, loading: false })
},
async getAllUsers({ commit, rootState, dispatch }) {
commit('setAllUsersLoading', true)
try {
const response = await axios.post(
url.searchUser,
@ -107,6 +131,7 @@ const actions = {
if (e.response)
if (e.response.data === 401) dispatch('logout', null, { root: true })
}
commit('setAllUsersLoading', false)
},
setFilter({ commit }, data) {
commit('setFilter', data)
@ -122,6 +147,12 @@ const getters = {
},
filter: state => {
return state.filter
},
usersLoading: state => {
return state.usersLoading
},
allUsersLoading: state => {
return state.allUsersLoading
}
}

View File

@ -24,7 +24,11 @@ const state = {
{ value: 10, text: 'Oktober' },
{ value: 11, text: 'November' },
{ value: 12, text: 'Dezember' }
]
],
allUsersLoading: false,
usersLoading: false,
emailLoading: false,
addUserLoading: false
}
const mutations = {
@ -73,7 +77,8 @@ const mutations = {
locked: users[user].locked,
autoLock: users[user].autoLock,
creditList: list,
expand: false
expand: false,
loading: false
})
}
}
@ -202,6 +207,7 @@ const mutations = {
if (data.locked !== undefined) state.users[index].locked = data.locked
if (data.limit !== undefined) state.users[index].limit = data.limit
if (data.autoLock !== undefined) state.users[index].autoLock = data.autoLock
if (data.loading !== undefined) state.users[index].loading = data.loading
},
setMails: (state, data) => {
state.errorMails = data
@ -217,12 +223,25 @@ const mutations = {
setYear: (state, value) => {
if (value) state.year++
else state.year--
},
setAllUsersLoading: (state, value) => {
state.allUsersLoading = value
},
setUsersLoading: (state, value) => {
state.usersLoading = value
},
setEMailLoading: (state, value) => {
state.emailLoading = value
},
setAddUserLoading: (state, value) => {
state.addUserLoading = value
}
}
const actions = {
// eslint-disable-next-line no-unused-vars
async getAllUsers({ commit, rootState, dispatch }) {
commit('setAllUsersLoading', true)
try {
const response = await axios.post(
url.searchUser,
@ -236,8 +255,10 @@ const actions = {
if (err.response.status === 401)
dispatch('logout', null, { root: true })
}
commit('setAllUsersLoading', false)
},
async getUsers({ commit, rootState, dispatch }) {
commit('setUsersLoading', true)
try {
const response = await axios.get(url.getFinanzerMain, {
headers: { Token: rootState.login.user.accessToken }
@ -248,11 +269,13 @@ const actions = {
if (err.response.status === 401)
dispatch('logout', null, { root: true })
}
commit('setUsersLoading', false)
},
setActiveUser({ commit }, username) {
commit('setActiveUser', username)
},
async addAmount({ commit, rootState, dispatch }, data) {
commit('updateUsers', { username: data.user.username, loading: true })
try {
const response = await axios.post(
url.finanzerAddAmount,
@ -276,8 +299,10 @@ const actions = {
if (err.response.status === 401)
dispatch('logout', null, { root: true })
}
commit('updateUsers', { username: data.user.username, loading: false })
},
async addCredit({ commit, rootState, dispatch }, data) {
commit('updateUsers', { username: data.user.username, loading: true })
try {
const response = await axios.post(
url.finanzerAddCredit,
@ -301,8 +326,10 @@ const actions = {
if (err.response.status === 401)
dispatch('logout', null, { root: true })
}
commit('updateUsers', { username: data.user.username, loading: false })
},
async doLock({ commit, rootState, dispatch }, data) {
commit('updateUsers', { username: data.user.username, loading: true })
try {
const response = await axios.post(
url.lockUser,
@ -314,8 +341,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('updateUsers', { username: data.user.username, loading: false })
},
async saveConfig({ commit, rootState, dispatch }, data) {
commit('updateUsers', { username: data.user.username, loading: true })
try {
const response = await axios.post(
url.finanzerSetConfig,
@ -331,8 +360,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('updateUsers', { username: data.user.username, loading: false })
},
async addUser({ commit, rootState, dispatch }, data) {
commit('setAddUserLoading', true)
try {
const response = await axios.post(
url.finanzerAddUser,
@ -344,8 +375,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('setAddUserLoading', false)
},
async sendMails({ commit, rootState, dispatch }) {
commit('setEMailLoading', true)
try {
const response = await axios.get(url.finanzerSendAllMail, {
headers: { Token: rootState.login.user.accessToken }
@ -355,8 +388,10 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('setEMailLoading', false)
},
async sendMail({ commit, rootState, dispatch }, data) {
commit('updateUsers', { username: data.username, loading: true })
try {
const response = await axios.post(
url.finanzerSendOneMail,
@ -368,6 +403,7 @@ const actions = {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('updateUsers', { username: data.username, loading: false })
},
createYears({ commit }) {
commit('setYears')
@ -410,6 +446,15 @@ const getters = {
},
months: state => {
return state.months
},
allUsersLoading: state => {
return state.allUsersLoading
},
usersLoading: state => {
return state.usersLoading
},
addUserLoading: state => {
return state.addUserLoading
}
}

View File

@ -5,6 +5,8 @@ import url from '@/plugins/routes'
const state = {
user: {
username: null,
firstname: null,
lastname: null,
accessToken: null,
group: null
},
@ -30,12 +32,16 @@ const mutations = {
state.user.username = data.username
state.user.accessToken = data.accessToken
state.user.group = data.group
state.user.firstname = data.firstname
state.user.lastname = data.lastname
}
},
logout(state) {
state.user.accessToken = null
state.user.username = null
state.user.group = null
state.user.firstname = null
state.user.lastname = null
}
}
@ -44,12 +50,15 @@ const actions = {
commit('loginStart')
try {
const response = await axios.post(url.login, { ...loginData })
console.log(response.data)
localStorage.setItem(
'user',
JSON.stringify({
username: response.data.username,
accessToken: response.data.token,
group: response.data.group
group: response.data.group,
firstname: response.data.firstname,
lastname: response.data.lastname
})
)
commit('loginStop', null)
@ -66,7 +75,9 @@ const actions = {
commit('updateAccessToken', {
username: null,
accessToken: null,
group: null
group: null,
firstname: null,
lastname: null
})
}
},
@ -84,6 +95,9 @@ const actions = {
}
const getters = {
loggingIn: state => {
return state.loggingIn
},
getGroup: state => {
return state.user.group
},
@ -122,6 +136,9 @@ const getters = {
},
isLoggedIn: state => {
return state.user.accessToken ? true : false
},
user: state => {
return state.user
}
}

View File

@ -3,7 +3,8 @@ import url from '@/plugins/routes'
const state = {
month: [],
allUsers: []
allUsers: [],
disabled: false
}
const mutations = {
@ -45,7 +46,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Montag',
worker: []
worker: [],
loading: false
}
break
case 2:
@ -53,7 +55,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Dienstag',
worker: []
worker: [],
loading: false
}
break
case 3:
@ -66,7 +69,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Mittwoch',
worker: []
worker: [],
loading: false
}
}
break
@ -75,7 +79,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Donnerstag',
worker: []
worker: [],
loading: false
}
break
case 5:
@ -83,7 +88,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Freitag',
worker: []
worker: [],
loading: false
}
break
case 6:
@ -91,7 +97,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Samstag',
worker: []
worker: [],
loading: false
}
break
case 0:
@ -99,7 +106,8 @@ const mutations = {
id: currentDate.getDay(),
date: currentDate,
name: 'Sontag',
worker: []
worker: [],
loading: false
}
break
}
@ -146,7 +154,7 @@ const mutations = {
for (let day in state.month[week].days) {
if (state.month[week].days[day].date - date === 0) {
let worker = state.month[week].days[day].worker.find(a => {
return a.username === user.username
return a.username === user.username
})
if (!worker && data.com === 'add') {
state.month[week].days[day].worker.push({
@ -159,11 +167,24 @@ const mutations = {
}
}
}
},
setDayLoading: (state, { date, getters }) => {
let day = getters.getDay(date)
day.loading = true
},
setDayNotLoading: (state, { date, getters }) => {
let day = getters.getDay(date)
day.loading = false
},
setDisabled: (state, data) => {
state.disabled = data
}
}
const actions = {
createMonth({ commit }, date) {
commit('setDisabled', true)
commit('createMonth', date)
commit('setDisabled', false)
},
async getAllUsers({ commit, rootState, dispatch }) {
try {
@ -188,14 +209,14 @@ const actions = {
headers: { Token: rootState.login.user.accessToken }
}
)
console.log(response.data)
commit('updateMonth', {...response.data[0], com: 'add'})
commit('updateMonth', { ...response.data[0], com: 'add' })
} catch (e) {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
},
async getUser({ commit, rootState, dispatch }, data) {
async getUser({ commit, rootState, dispatch, getters }, data) {
commit('setDayLoading', { date: data.startdatetime, getters })
try {
const response = await axios.post(
url.vorstand.sm.getUser,
@ -205,6 +226,7 @@ const actions = {
for (let item = 0; item < response.data.length; item++) {
commit('updateMonth', { ...response.data[item], com: 'add' })
}
commit('setDayNotLoading', { date: data.startdatetime, getters })
} catch (e) {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
@ -219,11 +241,17 @@ const actions = {
{ ...data },
{ headers: { Token: rootState.login.user.accessToken } }
)
commit('updateMonth', {...data, com: 'delete'})
commit('updateMonth', { ...data, com: 'delete' })
} catch (e) {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
},
setDayLoading({ commit, getters }, date) {
commit('setDayLoading', { date, getters })
},
setDayNotLoading({ commit, getters }, date) {
commit('setDayNotLoading', { date, getters })
}
}
const getters = {
@ -232,6 +260,22 @@ const getters = {
},
allUsers: state => {
return state.allUsers
},
getDayLoading: (state, getters) => date => {
let day = getters.getDay(date)
return day.loading
},
getDay: state => date => {
for (let week = 0; week < state.month.length; week++) {
for (let day in state.month[week].days) {
if (state.month[week].days[day].date - date === 0) {
return state.month[week].days[day]
}
}
}
},
disabled: state => {
return state.disabled
}
}

View File

@ -3,7 +3,11 @@ import url from '@/plugins/routes'
const state = {
user: null,
creditList: []
creditList: [],
loading: false,
addLoading: false,
error: '',
days: []
}
const mutations = {
@ -11,6 +15,7 @@ const mutations = {
state.user = user
let list = {}
for (let creditList in user['creditList']) {
// eslint-disable-next-line no-console
console.log(creditList)
let amount = mutations.createAmount(user['creditList'][creditList])
let credit = mutations.createCredit(user['creditList'][creditList])
@ -19,6 +24,8 @@ const mutations = {
}
state.user.creditList = list
state.creditList = []
state.error = ''
// eslint-disable-next-line no-console
console.log(state.user)
},
createAmount(creditList) {
@ -115,22 +122,61 @@ const mutations = {
sum.nov_amount +
sum.dez_amount
return sum
},
setLoading(state, value) {
state.loading = value
},
setAddLoading(state, value) {
state.addLoading = value
},
setError(state, value) {
state.error = value
console.log(state)
},
createDays(state, date) {
let days = []
for (let i = 0; i <= 10; i++) {
days.push({
date: new Date(
date.getFullYear(),
date.getMonth(),
date.getDate() + i,
12
),
job: false,
workers: []
})
}
state.days = days
},
updateDay(state, data) {
const date = data.date
for (let day in state.days) {
if (state.days[day].date - date === 0) {
state.days[day].job = data.job
if (data.workers) state.days[day].workers = data.workers
}
}
}
}
const actions = {
async getUser({ commit, rootState, dispatch }) {
commit('setLoading', true)
try {
const response = await axios.get(url.userMain, {
headers: { Token: rootState.login.user.accessToken }
})
commit('setUser', response.data)
commit('setError', '')
} catch (e) {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('setLoading', false)
},
async addAmount({ commit, rootState, dispatch }, amount) {
commit('setAddLoading', true)
try {
const response = await axios.post(
url.userAddAmount,
@ -138,10 +184,60 @@ const actions = {
{ headers: { Token: rootState.login.user.accessToken } }
)
commit('setUser', response.data)
commit('setError', '')
} catch (e) {
if (e.response)
if (e.response.status === 401) dispatch('logout', null, { root: true })
}
commit('setAddLoading', false)
},
async saveConfig({ commit, rootState, dispatch }, data) {
commit('setLoading', true)
try {
const response = await axios.post(
url.user.config,
{ ...data },
{ headers: { Token: rootState.login.user.accessToken } }
)
console.log(response.data)
commit('setUser', response.data)
commit('setError', '')
} catch (e) {
if (e.response) {
if (e.response.status === 401) dispatch('logout', null, { root: true })
if (e.response.data) {
console.log(e.response.data)
commit('setError', e.response.data.error)
}
}
}
commit('setLoading', false)
},
createDays({ commit }, date) {
commit('createDays', date)
},
async updateDay({ commit, rootState, dispatch }, data) {
commit('setLoading', true)
try {
console.log('hier bin ich')
const response = await axios.post(
url.user.job,
{ date: data.date.getTime() / 1000 },
{ headers: { Token: rootState.login.user.accessToken } }
)
console.log(response.data)
commit('updateDay', { ...response.data, date: data.date })
} catch (e) {
if (e.response) {
if (e.response.status === 401) dispatch('logout', null, { root: true })
if (e.response.data) {
console.log(e.response.data, data.date)
commit('setError', e.response.data.error)
}
}
console.log(e)
}
commit('setLoading', false)
}
}
@ -156,6 +252,18 @@ const getters = {
if (currentYear > year) year = currentYear
}
return year
},
loading: state => {
return state.loading
},
addLoading: state => {
return state.addLoading
},
error: state => {
return state.error
},
days: state => {
return state.days
}
}

View File

@ -14,7 +14,6 @@
<v-text-field
label="Login"
name="login"
prepend-icon="person"
type="text"
v-model="username"
ref="first"
@ -22,21 +21,31 @@
doLogin({ username: username, password: password })
"
@input="resetLoginError"
/>
>
<template v-slot:prepend-inner>
<v-icon>{{account}}</v-icon>
</template>
</v-text-field>
<v-text-field
id="password"
label="Password"
name="password"
prepend-icon="lock"
type="password"
v-model="password"
@keyup.enter="
doLogin({ username: username, password: password })
"
@input="resetLoginError"
/>
>
<template v-slot:prepend-inner>
<v-icon>{{lock}}</v-icon>
</template>
</v-text-field>
</v-form>
<div class="text-center">
<v-progress-circular indeterminate v-if="loggingIn" />
</div>
</v-card-text>
<v-alert v-if="loginError" dense type="error">{{
loginError
@ -62,19 +71,21 @@
<script>
// eslint-disable-next-line no-unused-vars
import { mapActions } from 'vuex'
import { mapGetters } from 'vuex'
import { mapActions, mapGetters } from 'vuex'
import { mdiAccount, mdiLock } from '@mdi/js'
export default {
name: 'Login',
components: {},
data() {
return {
username: null,
password: null
password: null,
account: mdiAccount,
lock: mdiLock
}
},
methods: mapActions(['doLogin', 'resetLoginError']),
computed: mapGetters(['loginError'])
computed: mapGetters(['loginError', 'loggingIn'])
}
</script>

View File

@ -12,21 +12,21 @@
<v-list>
<v-list-item v-if="isUser" class="title" link to="/main/user/add">
<v-list-item-icon>
<v-icon>person</v-icon>
<v-icon>{{person}}</v-icon>
</v-list-item-icon>
<v-list-item-title>Account</v-list-item-title>
<v-list-item-title>{{user.firstname}} {{user.lastname}}</v-list-item-title>
</v-list-item>
<v-list-item v-if="isBar" class="title" link to="/main/bar/geruecht">
<v-list-item-icon>
<v-icon>local_bar</v-icon>
<v-icon>{{glass_cocktail}}</v-icon>
</v-list-item-icon>
<v-list-item-title>
Gerüchte
Bar
</v-list-item-title>
</v-list-item>
<v-list-item v-if="isFinanzer" class="title" link to="/main/finanzer/overview">
<v-list-item-icon>
<v-icon>attach_money</v-icon>
<v-icon>{{attach_money}}</v-icon>
</v-list-item-icon>
<v-list-item-title>Finanzer</v-list-item-title>
</v-list-item>
@ -39,7 +39,7 @@
<v-list>
<v-list-item>
<v-list-item-icon>
<v-icon>exit_to_app</v-icon>
<v-icon>{{exit_to_app}}</v-icon>
</v-list-item-icon>
<v-list-item-title>
<v-btn block text @click="logout">Logout</v-btn>
@ -54,8 +54,17 @@
<script>
import { mapActions, mapGetters } from 'vuex'
import {mdiAccount, mdiCurrencyEur, mdiExitToApp, mdiGlassCocktail} from '@mdi/js'
export default {
name: 'MainView',
data () {
return {
person: mdiAccount,
attach_money: mdiCurrencyEur,
exit_to_app: mdiExitToApp,
glass_cocktail: mdiGlassCocktail
}
},
components: { },
created() {
},
@ -70,7 +79,8 @@ export default {
isBar: 'isBar',
isUser: 'isUser',
isFinanzer: 'isFinanzer',
isLoggedIn: 'isLoggedIn'
isLoggedIn: 'isLoggedIn',
user: 'user'
})
}
}