ESAMuchRechner/client/pages/entry/[slug].vue

564 lines
12 KiB
Vue

<template>
<q-page>
<div class="row">
<div class="col-6">
<q-card class="q-ma-md">
<q-card-section>
<div class="text-h6">
Person hinzufügen
</div>
</q-card-section>
<q-card-section>
<q-input
v-model="personenNamensEingabeFeld"
label="Name"
maxlength="32"
counter
outlined
/>
</q-card-section>
<q-card-actions vertical>
<q-btn
color="primary"
label="Hinzufügen"
:disabled="personenNamensEingabeFeld === ''"
@click="personHinzufügen"
/>
</q-card-actions>
<q-card-section>
<q-checkbox
v-model="witzigeEffekte"
label="Witzige Effekte"
/>
<q-slider
v-model="FAULERDISKORUTSCHER"
:min="100"
:max="2000"
:step="50"
:disable="!witzigeEffekte"
snap
label
:label-value="FAULERDISKORUTSCHER + 'ms'"
@change="faulerWert => { DISKORUTSCHER = faulerWert }"
/>
</q-card-section>
</q-card>
</div>
<div class="col">
<q-card class="q-ma-md">
<q-card-section>
<div class="text-h6">
Blechstatus
</div>
<div class="text-subtitle2">
Geteilt auf {{ tabellenReihen.length }} Personen
</div>
</q-card-section>
<q-table
class="witzigeTabelleMitKlebendemHeader"
dense
:rows="tabellenReihen"
:columns="tabellenSpalten"
separator="cell"
row-key="name"
:rows-per-page-options="[0]"
virtual-scroll
>
<template #body-cell-name="props">
<q-td
:props="props"
>
<q-btn
flat
color="red"
size="small"
padding="xs"
icon="delete"
:disabled="!wirdDieShiftTasteGehalten"
@click="personRausschmeißen(props.value)"
/>
{{ props.value }}
</q-td>
</template>
<template #body-cell-geblecht="props">
<q-td
v-if="props.row.geblecht.length"
:props="props"
class="cursor-pointer"
:class="{
ichGehInDieDisko: witzigeEffekte
}"
@click="blechGesprächÖffnen(props.key)"
>
{{ props.value }}
</q-td>
<q-td
v-else
:props="props"
>
{{ props.value }}
</q-td>
</template>
</q-table>
</q-card>
</div>
</div>
<div class="row">
<div class="col">
<q-card class="q-ma-md">
<q-card-section>
<div class="text-h6">
Geld blechen
</div>
</q-card-section>
<q-card-section>
<q-select
v-model="personenAuswähler"
class="q-my-md"
label="Person"
outlined
:options="personenAuswahlMöglichkeiten"
/>
<q-input
v-model.number="grundEingabeFeld"
class="q-my-md"
label="Grund / Ausgabe"
maxlength="32"
counter
outlined
/>
<q-input
v-model.number="geldEingabeFeld"
class="q-my-md"
label="Geld"
maxlength="8"
counter
outlined
/>
<q-select
v-model="schuldnerAuswähler"
multiple
class="q-my-md"
label="Schuldnerauswahl"
outlined
use-chips
:options="personenAuswahlMöglichkeiten"
/>
</q-card-section>
<q-card-actions vertical>
<q-btn
color="primary"
label="Blechen"
:disabled="!personenAuswähler"
@click="geldBlechen"
/>
</q-card-actions>
</q-card>
</div>
<div class="col">
<q-card class="q-ma-md">
<q-card-section>
<div class="text-h6">
Gequetschter Blechstatus
</div>
<div class="text-subtitle2">
Geteilt auf {{ tabellenReihen.length }} Personen
</div>
</q-card-section>
<q-table
class="witzigeTabelleMitKlebendemHeader"
dense
:rows="gequetschteTabellenReihen"
:columns="tabellenSpalten"
separator="cell"
row-key="name"
:rows-per-page-options="[0]"
virtual-scroll
>
<template #body-cell-geblecht="props">
<q-td
v-if="props.row.geblecht.length"
:props="props"
class="cursor-pointer"
:class="{
ichGehInDieDisko: witzigeEffekte
}"
@click="blechGesprächÖffnen(props.key)"
>
{{ props.value }}
</q-td>
<q-td
v-else
:props="props"
>
{{ props.value }}
</q-td>
</template>
</q-table>
</q-card>
</div>
</div>
</q-page>
<q-dialog
v-model="blechGespräch"
full-width
>
<q-card full-width>
<q-card-section class="row items-center q-pb-none">
<q-space />
<q-btn
v-close-popup
icon="close"
flat
round
dense
/>
</q-card-section>
<q-table
class="witzigeTabelleMitKlebendemHeader"
dense
:rows="blechGesprächZeilen"
:columns="blechGesprächSpalten"
separator="cell"
row-key="grund"
:rows-per-page-options="[0]"
virtual-scroll
>
<template #body-cell-grund="props">
<q-td
:props="props"
>
<q-btn
flat
color="red"
size="small"
padding="xs"
icon="delete"
:disabled="!wirdDieShiftTasteGehalten"
@click="blechungLöschen(props.rowIndex)"
/>
{{ props.value }}
</q-td>
</template>
</q-table>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { usePersonenStore } from '@/stores/personen-store';
import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Loading } from 'quasar';
const route = useRoute();
Loading.show();
const personenStore = usePersonenStore();
await personenStore.loadRemote(route.params.slug as string);
Loading.hide();
const personenNamensEingabeFeld = ref('');
const personenAuswähler = ref('');
const schuldnerAuswähler: Ref<string[] | null> = ref(null);
watch(personenAuswähler, () => {
schuldnerAuswähler.value = personenAuswahlMöglichkeiten.value;
});
const blechungLöschen = (reihenNummerDerBlechung: number) => {
const person = personenStore.personen[blechGesprächPerson.value];
person.geblecht.splice(reihenNummerDerBlechung, 1);
if (!person.geblecht.length) {
blechGespräch.value = false;
}
};
const geldEingabeFeld = ref(0.0);
const grundEingabeFeld = ref('');
const blechGespräch = ref(false);
const blechGesprächPerson = ref('');
const witzigeEffekte = ref(false);
const FAULERDISKORUTSCHER = ref(1000);
const DISKORUTSCHER = ref(1000);
const blechDiskoGeschwindigkeit = computed(() => {
return `${DISKORUTSCHER.value * 5}ms`;
});
const schuldenDiskoGeschwindigkeit = computed(() => {
return `${DISKORUTSCHER.value}ms`;
});
const blechGesprächÖffnen = (nameDerPerson: string) => {
blechGespräch.value = true;
blechGesprächPerson.value = nameDerPerson;
};
const blechGesprächZeilen = computed(() => {
if (!blechGesprächPerson.value) return [];
const person = personenStore.personen[blechGesprächPerson.value];
return person.geblecht;
});
const wirdDieShiftTasteGehalten = ref(false);
document.onkeydown = event => {
wirdDieShiftTasteGehalten.value = event.shiftKey;
};
document.onkeyup = event => {
wirdDieShiftTasteGehalten.value = event.shiftKey;
};
function speicherLeute () {
// personenStore.save();
}
function personHinzufügen () {
const name = personenNamensEingabeFeld.value;
personenStore.personen[name] = {
name,
geblecht: [],
};
personenNamensEingabeFeld.value = '';
speicherLeute();
}
function personRausschmeißen (personenName: string) {
delete personenStore.personen[personenName];
speicherLeute();
}
function geldBlechen () {
const p = personenStore.personen[personenAuswähler.value];
p.geblecht.push({
grund: grundEingabeFeld.value,
geld: geldEingabeFeld.value,
schuldner: schuldnerAuswähler.value,
});
grundEingabeFeld.value = '';
geldEingabeFeld.value = 0.0;
speicherLeute();
}
function blechSumme (blechListe: any[], nameDerPerson = '') {
let gesamtBlechGeld = 0;
for (const blech of blechListe) {
if (!nameDerPerson) {
gesamtBlechGeld += blech.geld;
continue;
}
if (!blech.schuldner.includes(nameDerPerson)) continue;
gesamtBlechGeld += blech.geld / blech.schuldner.length;
}
return gesamtBlechGeld;
}
const blechGesprächSpalten = [
{
name: 'grund',
required: true,
label: 'Grund / Ausgabe',
align: 'left',
field: 'grund',
sortable: true,
},
{
name: 'geld',
label: 'Geld / Kosten',
field: 'geld',
sortable: true,
format: (reihenWert: string) => reihenWert ? `${gleitzahlenAnalysierer(reihenWert) || '0.00'}` : '',
},
{
name: 'schuldner',
label: 'Schuldner',
field: 'schuldner',
sortable: false,
format: (reihenWert: any) => reihenWert.join(', '),
},
] as any;
const tabellenSpalten = computed(() => {
const cols = [
{
name: 'name',
required: true,
label: 'Name',
align: 'left',
field: 'name',
sortable: true,
},
{
name: 'geblecht',
label: 'Geblecht',
field: 'geblecht',
sortable: true,
format: (reihenWert: any[]) => reihenWert ? `${gleitzahlenAnalysierer(blechSumme(reihenWert)) || '0.00'}` : '',
},
] as any;
for(const [name] of Object.entries(personenStore.personen)) {
cols.push({
name: `an-${name}`,
label: `An ${name}`,
// classes: (reihe: any) => witzigeEffekte.value && reihe.an[name] ? 'duMusstNochGeldZahlenDuLackaffe' : '',
// field: (reihe: any) => reihe.an[name],
// format: (reihenWert: any) => reihenWert ? `${gleitzahlenAnalysierer(reihenWert) || '0.00'} €` : '',
});
}
return cols;
});
function gleitzahlenAnalysierer (wert: string | number) {
return parseFloat(`${wert}`).toFixed(2);
}
function reihenRechner () {
const reihenResultate = [];
const personenEinträge: [string, any][] = Object.entries(personenStore.personen);
for(const [name, datenDerPerson] of personenEinträge) {
const personenObjekt = {
name,
geblecht: datenDerPerson.geblecht,
an: {},
} as any;
for(const [nameDerAnderenPerson, datenDerAnderenPerson] of personenEinträge) {
if (name === nameDerAnderenPerson) continue;
const blechTeiler = blechSumme(datenDerAnderenPerson.geblecht, name); // / Object.keys(personenStore.personen).length;
personenObjekt.an[nameDerAnderenPerson] = blechTeiler;
}
reihenResultate.push(personenObjekt);
}
return reihenResultate;
}
const tabellenReihen = computed(() => {
return reihenRechner();
});
const gequetschteTabellenReihen = computed(() => {
const neueZeilen = [];
const leuteKlon = reihenRechner();
for (const klonPersonObjekt of leuteKlon) {
const personenObjekt = {
name: klonPersonObjekt.name,
geblecht: klonPersonObjekt.geblecht,
an: klonPersonObjekt.an,
};
for (const person of leuteKlon) {
const name = person.name;
if (name === personenObjekt.name) continue;
const unserAn = personenObjekt.an[name];
const anderAn = person.an[personenObjekt.name];
if (unserAn < anderAn) continue;
personenObjekt.an[name] = unserAn - anderAn;
person.an[personenObjekt.name] = 0;
}
neueZeilen.push(klonPersonObjekt);
}
return neueZeilen;
});
const personenAuswahlMöglichkeiten = computed(() => {
const auswahlMöglichkeiten = [];
for(const [name] of Object.entries(personenStore.personen)) {
auswahlMöglichkeiten.push(name);
}
return auswahlMöglichkeiten;
});
</script>
<style>
.witzigeTabelleMitKlebendemHeader {
height: 400px;
}
.witzigeTabelleMitKlebendemHeader thead tr th {
position: sticky;
z-index: 1;
}
.witzigeTabelleMitKlebendemHeader thead tr:first-child th {
top: 0;
background-color: #323232;
}
.ichGehInDieDisko {
animation: diskoNeu v-bind(blechDiskoGeschwindigkeit) linear infinite;
background: linear-gradient(238deg, #7c4200, #760043, #4c007e, #001f86, #005a68, #194830);
background-size: 1200% 1200%;
}
/* .ICHBINSOHARTINDERDISKOBRUDIALTERDIGGA {
animation: diskoNeu 1s linear infinite;
background: linear-gradient(238deg, #7c4200, #760043, #4c007e, #001f86, #005a68, #194830);
background-size: 1200% 1200%;
} */
.duMusstNochGeldZahlenDuLackaffe {
animation: schuldenDisko v-bind(schuldenDiskoGeschwindigkeit) linear infinite;
}
/* .ZAHLMIRENDLICHDASGELDDUAFFE {
animation: schuldenDisko 0.25s linear infinite;
} */
@keyframes diskoNeu {
0% { background-position: 0% 50% }
50% { background-position: 100% 50% }
100% { background-position: 0% 50% }
}
@keyframes schuldenDisko {
0% { background-color: rgb(100, 0, 0); }
50% { background-color: black; }
100% { background-color: rgb(100, 0, 0); }
}
</style>