forked from Kispi/Core
All checks were successful
continuous-integration/drone/push Build is passing
204 lines
No EOL
5.4 KiB
Vue
204 lines
No EOL
5.4 KiB
Vue
<template>
|
|
<div
|
|
v-if="!isAuthenticated"
|
|
class="flex min-h-full flex-col p-6"
|
|
>
|
|
<AtomInput
|
|
v-model="searchQuery"
|
|
placeholder="Firmenname eingeben"
|
|
class="mb-4"
|
|
/>
|
|
<MoleculeDataTable
|
|
v-if="companies"
|
|
class="cursor-pointer"
|
|
:table-headers="companyTableHeaders"
|
|
:data="companies"
|
|
hide-header
|
|
@click="showLoginDialog"
|
|
/>
|
|
<MoleculeLoginModal
|
|
id="login-modal"
|
|
ref="loginModal"
|
|
v-model="password"
|
|
:title="selectedCompany?.name ?? ''"
|
|
description="Bitte gib dein Passwort ein, um das Firmenportal anzuzeigen."
|
|
:error="error"
|
|
@login="login"
|
|
@close="password = ''; error = ''"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-else-if="company"
|
|
class="flex min-h-full flex-col p-6"
|
|
>
|
|
<div class="mb-4 flex flex-col gap-4">
|
|
<div class="flex items-center justify-between">
|
|
<h1 class="text-4xl">{{ company.name }}</h1>
|
|
<button
|
|
class="btn-primary btn w-48"
|
|
@click="logout()"
|
|
>
|
|
<ArrowLeftOnRectangleIcon class="h-6 w-6" />
|
|
Abmelden
|
|
</button>
|
|
</div>
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="text-2xl">500,00 Batzen</h2>
|
|
<button class="btn-primary btn-disabled btn w-48">
|
|
<BanknotesIcon class="h-6 w-6" />
|
|
Transaktionen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<MoleculeDataTable
|
|
v-if="accounts"
|
|
:table-headers="accountTableHeaders"
|
|
:data="accounts"
|
|
@select-shift="selectShift"
|
|
@select-wage="selectWage"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
|
import { RecordSubscription, UnsubscribeFunc } from 'pocketbase';
|
|
import { AccountsResponse, CompaniesResponse } from '../../types/pocketbase.types';
|
|
import { AccountService } from '../../services/account.service';
|
|
import { CompanyService } from '../../services/company.service';
|
|
import { Shifts } from '../../enums/shift.enum';
|
|
import { ArrowLeftOnRectangleIcon, BanknotesIcon } from '@heroicons/vue/24/outline';
|
|
import AtomInput from '../atoms/AtomInput.vue';
|
|
import MoleculeDataTable, { TableHeaderType } from '../molecules/MoleculeDataTable.vue';
|
|
import MoleculeLoginModal from '../molecules/MoleculeLoginModal.vue';
|
|
|
|
const loginModal = ref<InstanceType<typeof MoleculeLoginModal>>();
|
|
const searchQuery = ref('');
|
|
const password = ref('');
|
|
const companies = ref<CompaniesResponse[]>([]);
|
|
const initCompanies = ref<CompaniesResponse[]>([]);
|
|
const selectedCompany = ref<CompaniesResponse>();
|
|
const company = ref<CompaniesResponse>();
|
|
const accounts = ref<AccountsResponse[]>([]);
|
|
const isAuthenticated = ref(false);
|
|
const accountsSubscription = ref<UnsubscribeFunc>();
|
|
const error = ref('');
|
|
|
|
const companyTableHeaders = [
|
|
{
|
|
title: '',
|
|
key: 'name',
|
|
type: TableHeaderType.STRING,
|
|
},
|
|
];
|
|
|
|
const accountTableHeaders = [
|
|
{
|
|
title: 'Vorname',
|
|
key: 'firstName',
|
|
type: TableHeaderType.STRING,
|
|
},
|
|
{
|
|
title: 'Nachname',
|
|
key: 'lastName',
|
|
type: TableHeaderType.STRING,
|
|
},
|
|
{
|
|
title: 'Schicht',
|
|
key: 'shift',
|
|
type: TableHeaderType.SHIFT,
|
|
},
|
|
{
|
|
title: 'Lohn',
|
|
key: 'wageFactor',
|
|
type: TableHeaderType.WAGE,
|
|
},
|
|
];
|
|
|
|
async function getData() {
|
|
initCompanies.value = await CompanyService.getCompanies();
|
|
companies.value = initCompanies.value;
|
|
}
|
|
|
|
watch(
|
|
searchQuery,
|
|
(value) => {
|
|
search(value);
|
|
},
|
|
);
|
|
|
|
function search(value: string): void {
|
|
if(initCompanies.value) {
|
|
companies.value = initCompanies.value.filter((company) =>
|
|
company.name?.toLocaleLowerCase().includes(value.toLocaleLowerCase()),
|
|
);
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
isAuthenticated.value = CompanyService.isAuthenticated();
|
|
if(isAuthenticated.value) {
|
|
init();
|
|
} else {
|
|
getData();
|
|
}
|
|
});
|
|
|
|
async function init() {
|
|
company.value = await CompanyService.getCompany();
|
|
accounts.value = await AccountService.getAccountsByCompanyId(company.value.id);
|
|
accountsSubscription.value = await AccountService.subscribeToAccountChanges(async (data: RecordSubscription<AccountsResponse>) => {
|
|
if(data.action === 'update') {
|
|
accounts.value = accounts.value.map((account) => {
|
|
if(account.id === data.record.id) {
|
|
return data.record;
|
|
}
|
|
return account;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function showLoginDialog(id: string): void {
|
|
selectedCompany.value = companies.value.find((company) => company.id === id);
|
|
loginModal.value?.show();
|
|
}
|
|
|
|
async function login(): Promise<void> {
|
|
if(selectedCompany.value) {
|
|
try {
|
|
await CompanyService.login(selectedCompany.value?.username, password.value);
|
|
} catch {
|
|
error.value = 'Fehler beim Login. Bitte Passwort überprüfen.';
|
|
return;
|
|
}
|
|
isAuthenticated.value = true;
|
|
await init();
|
|
loginModal.value?.close();
|
|
}
|
|
}
|
|
|
|
async function selectShift(shiftChange: {id: string, shift: Shifts}): Promise<void> {
|
|
await AccountService.updateShift(shiftChange.id, shiftChange.shift);
|
|
}
|
|
|
|
async function selectWage(wageChange: {id: string, wageFactor: number}): Promise<void> {
|
|
await AccountService.updateWage(wageChange.id, wageChange.wageFactor);
|
|
}
|
|
|
|
function logout() {
|
|
CompanyService.logout();
|
|
isAuthenticated.value = false;
|
|
selectedCompany.value = undefined;
|
|
company.value = undefined;
|
|
accounts.value = [];
|
|
getData();
|
|
}
|
|
|
|
onUnmounted(() => {
|
|
accountsSubscription.value?.();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
</style> |