forked from Kispi/Core
feat(webapp): add option to modify the account number
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
fe2eabaffc
commit
5aea42d33a
4 changed files with 128 additions and 12 deletions
|
@ -0,0 +1,84 @@
|
||||||
|
<template>
|
||||||
|
<AtomModal
|
||||||
|
:id="id"
|
||||||
|
ref="modal"
|
||||||
|
:title="title"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<div class="flex place-items-center justify-between">
|
||||||
|
<AtomInput
|
||||||
|
v-model="accountNumber"
|
||||||
|
class="w-4/12"
|
||||||
|
@keyup.esc="modal?.close()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<template #action>
|
||||||
|
<label
|
||||||
|
class="btn gap-2"
|
||||||
|
:for="id"
|
||||||
|
@click="modal?.close()"
|
||||||
|
>
|
||||||
|
<XCircleIcon class="h-6 w-6" />
|
||||||
|
Abbrechen
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
class="btn gap-2"
|
||||||
|
@click="handleSubmit()"
|
||||||
|
>
|
||||||
|
<CheckCircleIcon class="h-6 w-6" />
|
||||||
|
Speichern
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</AtomModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { CheckCircleIcon, XCircleIcon } from '@heroicons/vue/24/outline';
|
||||||
|
import AtomModal from '../atoms/AtomModal.vue';
|
||||||
|
import AtomInput from '../atoms/AtomInput.vue';
|
||||||
|
|
||||||
|
const modal = ref<InstanceType<typeof AtomModal>>();
|
||||||
|
const accountNumber = ref('');
|
||||||
|
const accountId = ref('');
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['submit']);
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
accountNumber.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
if(!accountNumber.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('submit', {
|
||||||
|
id: accountId.value,
|
||||||
|
accountNumber: accountNumber.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show: (id: string) => {
|
||||||
|
accountId.value = id;
|
||||||
|
modal.value?.show();
|
||||||
|
},
|
||||||
|
close: () => modal.value?.close(),
|
||||||
|
isOpen: () => modal.value?.isOpen(),
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -20,7 +20,7 @@
|
||||||
<td
|
<td
|
||||||
v-for="header in tableHeaders"
|
v-for="header in tableHeaders"
|
||||||
:class="{
|
:class="{
|
||||||
'text-center': header.type == TableHeaderType.BUTTON_ACCOUNT,
|
'text-center': [TableHeaderType.BUTTON_ACCOUNT, TableHeaderType.BUTTON_CHANGE_ACCOUNT_NUMBER].includes(header.type),
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span v-if="header.type === TableHeaderType.STRING">
|
<span v-if="header.type === TableHeaderType.STRING">
|
||||||
|
@ -55,12 +55,28 @@
|
||||||
v-if="header.type === TableHeaderType.BUTTON_ACCOUNT"
|
v-if="header.type === TableHeaderType.BUTTON_ACCOUNT"
|
||||||
:to="`/bank?accountNumber=${entry.accountNumber}`"
|
:to="`/bank?accountNumber=${entry.accountNumber}`"
|
||||||
class="btn-ghost btn-sm btn p-1"
|
class="btn-ghost btn-sm btn p-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="tooltip normal-case"
|
||||||
|
data-tip="Transaktionen anzeigen"
|
||||||
>
|
>
|
||||||
<CurrencyDollarIcon class="h-6 w-6" />
|
<CurrencyDollarIcon class="h-6 w-6" />
|
||||||
|
</div>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
<span
|
||||||
|
v-if="header.type === TableHeaderType.BUTTON_CHANGE_ACCOUNT_NUMBER"
|
||||||
|
class="btn-ghost btn-sm btn p-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="tooltip normal-case"
|
||||||
|
data-tip="Kontonummer ändern"
|
||||||
|
@click="$emit('changeAccountNumber', entry.id)"
|
||||||
|
>
|
||||||
|
<CreditCardIcon class="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="header.type === TableHeaderType.WAGE"
|
v-if="header.type === TableHeaderType.WAGE"
|
||||||
:for="contactModalId"
|
|
||||||
class="flex items-center gap-2"
|
class="flex items-center gap-2"
|
||||||
>
|
>
|
||||||
<div class="dropdown-bottom dropdown">
|
<div class="dropdown-bottom dropdown">
|
||||||
|
@ -93,7 +109,7 @@ import { DateService } from '../../services/date.service';
|
||||||
import { CurrencyService } from '../../services/currency.service';
|
import { CurrencyService } from '../../services/currency.service';
|
||||||
import { SettingsService } from '../../services/settings.service';
|
import { SettingsService } from '../../services/settings.service';
|
||||||
import { Shifts } from '../../enums/shift.enum';
|
import { Shifts } from '../../enums/shift.enum';
|
||||||
import { ChevronDownIcon, CurrencyDollarIcon } from '@heroicons/vue/24/outline';
|
import { ChevronDownIcon, CreditCardIcon, CurrencyDollarIcon } from '@heroicons/vue/24/outline';
|
||||||
|
|
||||||
const settings = ref<SettingsResponse>();
|
const settings = ref<SettingsResponse>();
|
||||||
|
|
||||||
|
@ -108,11 +124,6 @@ defineProps({
|
||||||
type: Array as PropType<any[]>,
|
type: Array as PropType<any[]>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
contactModalId: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
hideHeader: {
|
hideHeader: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -128,6 +139,7 @@ defineEmits<{
|
||||||
click: [id: string],
|
click: [id: string],
|
||||||
selectShift: [{id: string, shift: Shifts}],
|
selectShift: [{id: string, shift: Shifts}],
|
||||||
selectWage: [{id: string, wageFactor: number}],
|
selectWage: [{id: string, wageFactor: number}],
|
||||||
|
changeAccountNumber: [id: string],
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function removeFocus() {
|
function removeFocus() {
|
||||||
|
@ -142,6 +154,7 @@ export enum TableHeaderType {
|
||||||
CURRENCY,
|
CURRENCY,
|
||||||
DATETIME,
|
DATETIME,
|
||||||
BUTTON_ACCOUNT,
|
BUTTON_ACCOUNT,
|
||||||
|
BUTTON_CHANGE_ACCOUNT_NUMBER,
|
||||||
WAGE,
|
WAGE,
|
||||||
SHIFT,
|
SHIFT,
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,21 @@
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
/>
|
/>
|
||||||
<MoleculeDataTable
|
<MoleculeDataTable
|
||||||
v-if="accounts"
|
v-if="accounts && changeAccountNumberModal"
|
||||||
:table-headers="tableHeaders"
|
:table-headers="tableHeaders"
|
||||||
:data="accounts"
|
:data="accounts"
|
||||||
|
@change-account-number="changeAccountNumberModal.show($event);"
|
||||||
|
/>
|
||||||
|
<MoleculeChanceAccountNumberModal
|
||||||
|
id="changeAccountNumber"
|
||||||
|
ref="changeAccountNumberModal"
|
||||||
|
title="Kontonummer ändern"
|
||||||
|
@submit="changeAccountNumber"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// TODO: Add button in each row to change the accountNumber inside an modal
|
|
||||||
|
|
||||||
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
import { useEventBus } from '@vueuse/core';
|
import { useEventBus } from '@vueuse/core';
|
||||||
import { UnsubscribeFunc } from 'pocketbase';
|
import { UnsubscribeFunc } from 'pocketbase';
|
||||||
|
@ -30,10 +35,12 @@ import { AuthService } from '../../services/auth.service';
|
||||||
import AtomInput from '../atoms/AtomInput.vue';
|
import AtomInput from '../atoms/AtomInput.vue';
|
||||||
import MoleculeDataTable, { TableHeaderType } from '../molecules/MoleculeDataTable.vue';
|
import MoleculeDataTable, { TableHeaderType } from '../molecules/MoleculeDataTable.vue';
|
||||||
import MoleculeAuthDialog from '../molecules/MoleculeAuthDialog.vue';
|
import MoleculeAuthDialog from '../molecules/MoleculeAuthDialog.vue';
|
||||||
|
import MoleculeChanceAccountNumberModal from '../molecules/MoleculeChanceAccountNumberModal.vue';
|
||||||
|
|
||||||
const isAdmin = ref(false);
|
const isAdmin = ref(false);
|
||||||
const accountsSubscription = ref<UnsubscribeFunc>();
|
const accountsSubscription = ref<UnsubscribeFunc>();
|
||||||
const transactionsSubscription = ref<UnsubscribeFunc>();
|
const transactionsSubscription = ref<UnsubscribeFunc>();
|
||||||
|
const changeAccountNumberModal = ref<InstanceType<typeof MoleculeChanceAccountNumberModal>>();
|
||||||
|
|
||||||
const accounts = ref<AccountsListResponse<number, string>[]>([]);
|
const accounts = ref<AccountsListResponse<number, string>[]>([]);
|
||||||
const initAccounts = ref<AccountsListResponse<number, string>[]>([]);
|
const initAccounts = ref<AccountsListResponse<number, string>[]>([]);
|
||||||
|
@ -69,6 +76,11 @@ const tableHeaders = [
|
||||||
key: '',
|
key: '',
|
||||||
type: TableHeaderType.BUTTON_ACCOUNT,
|
type: TableHeaderType.BUTTON_ACCOUNT,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Knr. änd.',
|
||||||
|
key: '',
|
||||||
|
type: TableHeaderType.BUTTON_CHANGE_ACCOUNT_NUMBER,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
useEventBus<boolean>('isAdmin').on(state => {
|
useEventBus<boolean>('isAdmin').on(state => {
|
||||||
|
@ -99,6 +111,10 @@ function search(value: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeAccountNumber(account: {id: string, accountNumber: string}) {
|
||||||
|
AccountService.updateAccountNumber(account.id, account.accountNumber);
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isAdmin.value = AuthService.isAdmin();
|
isAdmin.value = AuthService.isAdmin();
|
||||||
if(isAdmin.value) {
|
if(isAdmin.value) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ export class AccountService {
|
||||||
public static async addAccount(account: AccountsRecord): Promise<AccountsResponse> {
|
public static async addAccount(account: AccountsRecord): Promise<AccountsResponse> {
|
||||||
return COLLECTION.create(account, { $cancelKey: `${account.firstName}.${account.lastName}.${account.grade}` });
|
return COLLECTION.create(account, { $cancelKey: `${account.firstName}.${account.lastName}.${account.grade}` });
|
||||||
}
|
}
|
||||||
|
public static async updateAccountNumber(accountId: string, accountNumber: string): Promise<AccountsResponse> {
|
||||||
|
return COLLECTION.update(accountId, { accountNumber });
|
||||||
|
}
|
||||||
public static async updateShift(accountId: string, shift: string): Promise<AccountsResponse> {
|
public static async updateShift(accountId: string, shift: string): Promise<AccountsResponse> {
|
||||||
return COLLECTION.update(accountId, { shift });
|
return COLLECTION.update(accountId, { shift });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue