add new feature report page
This commit is contained in:
@@ -4,7 +4,7 @@ go 1.25.4
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.tecamino.com/paadi/access-handler v1.0.34
|
gitea.tecamino.com/paadi/access-handler v1.0.34
|
||||||
gitea.tecamino.com/paadi/memberDB v1.1.19
|
gitea.tecamino.com/paadi/memberDB v1.1.27
|
||||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
|
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
|
||||||
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1
|
||||||
github.com/gin-contrib/cors v1.7.6
|
github.com/gin-contrib/cors v1.7.6
|
||||||
@@ -14,7 +14,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.tecamino.com/paadi/dbHandler v1.1.10 // indirect
|
gitea.tecamino.com/paadi/dbHandler v1.1.11 // indirect
|
||||||
github.com/bytedance/sonic v1.14.0 // indirect
|
github.com/bytedance/sonic v1.14.0 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
gitea.tecamino.com/paadi/access-handler v1.0.34 h1:6P65HiusSfvgv/ezOvxSahqyRJMK9UrxtGsz6loLoUk=
|
gitea.tecamino.com/paadi/access-handler v1.0.34 h1:6P65HiusSfvgv/ezOvxSahqyRJMK9UrxtGsz6loLoUk=
|
||||||
gitea.tecamino.com/paadi/access-handler v1.0.34/go.mod h1:HyMp1WvzmqLw8Ljt3r1qlF8fY+T5WFXr9Da/CTIM0H8=
|
gitea.tecamino.com/paadi/access-handler v1.0.34/go.mod h1:HyMp1WvzmqLw8Ljt3r1qlF8fY+T5WFXr9Da/CTIM0H8=
|
||||||
gitea.tecamino.com/paadi/dbHandler v1.1.10 h1:zZQbDTJ0bu6CIW90Zms8yYIzTLHtWPNhVKRxLUXEDuE=
|
gitea.tecamino.com/paadi/dbHandler v1.1.11 h1:hTpMWRr4dW7TkiBnEku0/3ggDC7/uP82U9paRKY/QEs=
|
||||||
gitea.tecamino.com/paadi/dbHandler v1.1.10/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
gitea.tecamino.com/paadi/dbHandler v1.1.11/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
|
||||||
gitea.tecamino.com/paadi/memberDB v1.1.19 h1:khbhtqS7rXTuOsWwxTO6rm13mIDjnBmJaTcJY4jmpQw=
|
gitea.tecamino.com/paadi/memberDB v1.1.27 h1:UJ/CHKc2CKd+TZ5HiGMK6p/A8wNqGUy9JjpmaPtKrEA=
|
||||||
gitea.tecamino.com/paadi/memberDB v1.1.19/go.mod h1:VBsORoIIhh0/RM5AvmaAjMEM2/cNaIT2TqDL1VDcov4=
|
gitea.tecamino.com/paadi/memberDB v1.1.27/go.mod h1:uLoKel+EcuXUzxAY5ugfWh640TSomfTJR+g8Jfe8YKI=
|
||||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 h1:vAq7mwUxlxJuLzCQSDMrZCwo8ky5usWi9Qz+UP+WnkI=
|
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 h1:vAq7mwUxlxJuLzCQSDMrZCwo8ky5usWi9Qz+UP+WnkI=
|
||||||
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1/go.mod h1:+tmf1rjPaKEoNeUcr1vdtoFIFweNG3aUGevDAl3NMBk=
|
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1/go.mod h1:+tmf1rjPaKEoNeUcr1vdtoFIFweNG3aUGevDAl3NMBk=
|
||||||
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE=
|
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE=
|
||||||
|
|||||||
@@ -158,6 +158,8 @@ func main() {
|
|||||||
auth.POST("/events/delete/attendees", dbHandler.DeleteAttendee)
|
auth.POST("/events/delete/attendees", dbHandler.DeleteAttendee)
|
||||||
auth.POST("/events/delete", dbHandler.DeleteEvent)
|
auth.POST("/events/delete", dbHandler.DeleteEvent)
|
||||||
|
|
||||||
|
auth.POST("/report", dbHandler.GetReport)
|
||||||
|
|
||||||
auth.POST("/groups/add", dbHandler.NewGroup)
|
auth.POST("/groups/add", dbHandler.NewGroup)
|
||||||
auth.POST("/groups/edit", dbHandler.UpdateGroup)
|
auth.POST("/groups/edit", dbHandler.UpdateGroup)
|
||||||
auth.POST("/groups/delete", dbHandler.DeleteGroup)
|
auth.POST("/groups/delete", dbHandler.DeleteGroup)
|
||||||
|
|||||||
@@ -156,3 +156,10 @@ numberOfEvents: Anzau Veranstautige
|
|||||||
numberOfResponsibles: Anzau Veratwortläche
|
numberOfResponsibles: Anzau Veratwortläche
|
||||||
numberOfGroups: Anzau Gruppe
|
numberOfGroups: Anzau Gruppe
|
||||||
selectDates: Datumuswauh
|
selectDates: Datumuswauh
|
||||||
|
apply: Awende
|
||||||
|
minimal: Minimal
|
||||||
|
maximal: Maximal
|
||||||
|
average: Durchschnitt
|
||||||
|
filterEventName: Verastautig filtere
|
||||||
|
hintFilterEventName: "*'IIgabe'* * oder % als filler vorher oder nächer"
|
||||||
|
total: Gesamt
|
||||||
|
|||||||
@@ -156,3 +156,10 @@ numberOfEvents: Anzahl Veranstaltungen
|
|||||||
numberOfResponsibles: Anzahl Verantwortliche
|
numberOfResponsibles: Anzahl Verantwortliche
|
||||||
numberOfGroups: Anzahl Gruppe
|
numberOfGroups: Anzahl Gruppe
|
||||||
selectDates: Datumauswahl
|
selectDates: Datumauswahl
|
||||||
|
apply: Anwenden
|
||||||
|
minimal: Minimal
|
||||||
|
maximal: Maximal
|
||||||
|
average: Durchschnitt
|
||||||
|
filterEventName: Veranstaltung filtern
|
||||||
|
hintFilterEventName: "*'Eingabe'* * oder % als Filler vorher oder nachher"
|
||||||
|
total: Gesamt
|
||||||
|
|||||||
@@ -156,3 +156,10 @@ numberOfEvents: Amount of Events
|
|||||||
numberOfResponsibles: Amount of Responsibles
|
numberOfResponsibles: Amount of Responsibles
|
||||||
numberOfGroups: Amount of Groups
|
numberOfGroups: Amount of Groups
|
||||||
selectDates: Dateselection
|
selectDates: Dateselection
|
||||||
|
apply: Apply
|
||||||
|
minimal: Minimal
|
||||||
|
maximal: Maximal
|
||||||
|
average: Average
|
||||||
|
filterEventName: filter Events
|
||||||
|
hintFilterEventName: "*'Input'* * or % as filler before oder after"
|
||||||
|
total: Total
|
||||||
|
|||||||
@@ -156,3 +156,10 @@ numberOfEvents: Cantidad de eventos
|
|||||||
numberOfResponsibles: Número de responsables
|
numberOfResponsibles: Número de responsables
|
||||||
numberOfGroups: Número de grupos
|
numberOfGroups: Número de grupos
|
||||||
selectDates: Selección de fecha
|
selectDates: Selección de fecha
|
||||||
|
apply: Aplicar
|
||||||
|
minimal: Mínimo
|
||||||
|
maximal: Máximo
|
||||||
|
average: Promedio
|
||||||
|
filterEventName: filtrar eventos
|
||||||
|
hintFilterEventName: "*''Entrada'* * o % como relleno antes o después"
|
||||||
|
total: Total
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="q-gutter-sm">
|
<div
|
||||||
|
class="q-ma-sm q-gutter-sm"
|
||||||
|
:style="{ height: props.height + 'px', width: props.width + 'px' }"
|
||||||
|
>
|
||||||
<h6 class="text-center text-bold q-ma-md text-primary">{{ props.title }}</h6>
|
<h6 class="text-center text-bold q-ma-md text-primary">{{ props.title }}</h6>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
@@ -14,30 +17,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<q-date v-model="dateRange" range flat />
|
<q-date v-model="dateRange" range flat />
|
||||||
<div>
|
|
||||||
<q-badge color="secondary"> Total dates selected: {{ filteredDates.length }} </q-badge>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { i18n } from 'src/boot/lang';
|
import { i18n } from 'src/boot/lang';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: String,
|
title: String,
|
||||||
|
height: { type: Number, default: 400 },
|
||||||
|
width: { type: Number, default: 300 },
|
||||||
});
|
});
|
||||||
|
|
||||||
const startDate = new Date();
|
const startDate = new Date();
|
||||||
|
|
||||||
// Initial range (format: YYYY/MM/DD)
|
// Initial range (format: YYYY-MM-DD)
|
||||||
const dateRange = ref();
|
const dateRange = ref<string | { to: string; from: string }>('');
|
||||||
const selectedWeekdays = ref([0, 3]); // Default to weekdays
|
const selectedWeekdays = ref([0, 3]); // Default to weekdays
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:dates']);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
dateRange.value = date.formatDate(startDate, 'YYYY/MM/DD');
|
dateRange.value = date.formatDate(startDate, 'YYYY-MM-DD');
|
||||||
});
|
});
|
||||||
|
|
||||||
const weekdayOptions = [
|
const weekdayOptions = [
|
||||||
@@ -51,13 +54,14 @@ const weekdayOptions = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// The Logic: Calculate all specific dates within the range that match weekdays
|
// The Logic: Calculate all specific dates within the range that match weekdays
|
||||||
const filteredDates = computed(() => {
|
watch(dateRange, () => {
|
||||||
if (!dateRange.value) {
|
if (!dateRange.value) {
|
||||||
return [];
|
return [];
|
||||||
} else if (typeof dateRange.value === 'string') {
|
} else if (typeof dateRange.value === 'string') {
|
||||||
const current = new Date(dateRange.value);
|
const current = new Date(dateRange.value);
|
||||||
if (current !== undefined && selectedWeekdays.value.includes(current.getDay())) {
|
if (current !== undefined && selectedWeekdays.value.includes(current.getDay())) {
|
||||||
return [date.formatDate(current, 'YYYY/MM/DD')];
|
emit('update:dates', [date.formatDate(current, 'YYYY-MM-DD')]);
|
||||||
|
return [date.formatDate(current, 'YYYY-MM-DD')];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -69,10 +73,12 @@ const filteredDates = computed(() => {
|
|||||||
|
|
||||||
while (current <= end) {
|
while (current <= end) {
|
||||||
if (selectedWeekdays.value.includes(current.getDay())) {
|
if (selectedWeekdays.value.includes(current.getDay())) {
|
||||||
result.push(date.formatDate(current, 'YYYY/MM/DD'));
|
result.push(date.formatDate(current, 'YYYY-MM-DD'));
|
||||||
}
|
}
|
||||||
current = date.addToDate(current, { days: 1 });
|
current = date.addToDate(current, { days: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit('update:dates', result);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
53
src/components/ReportStat.vue
Normal file
53
src/components/ReportStat.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<q-card class="col-auto">
|
||||||
|
<div class="row q-col-gutter-xs">
|
||||||
|
<div v-for="opt in props.amounts" :key="opt.name">
|
||||||
|
<q-card class="q-ma-xs" flat bordered>
|
||||||
|
<q-item dense>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="text-bold text-primary text-center">
|
||||||
|
{{ opt.name }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<q-card-section>
|
||||||
|
<div class="column justify-between items-center q-mb-xs">
|
||||||
|
<span class="text-bold text-grey-7 text-caption">{{ $t('events') }}</span>
|
||||||
|
<q-badge color="black" outline class="text-bold">{{ opt.events }}</q-badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column justify-between items-center q-mb-xs">
|
||||||
|
<span class="text-bold text-grey-7 text-caption">{{ $t('minimal') }}</span>
|
||||||
|
<q-badge color="secondary" outline class="text-bold">{{ opt.minimal }}</q-badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column justify-between items-center q-mb-xs">
|
||||||
|
<span class="text-bold text-grey-7 text-caption">{{ $t('average') }}</span>
|
||||||
|
<q-badge color="secondary" outline class="text-bold">{{ opt.average }}</q-badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column justify-between items-center q-mb-xs">
|
||||||
|
<span class="text-bold text-grey-7 text-caption">{{ $t('maximal') }}</span>
|
||||||
|
<q-badge color="primary" outline class="text-bold">{{ opt.maximal }}</q-badge>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Amount } from 'src/vueLib/models/report';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
amounts: {
|
||||||
|
type: Object as PropType<Amount[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,36 +1,233 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="rows">
|
<q-inner-loading
|
||||||
|
:showing="loading"
|
||||||
|
label="Please wait..."
|
||||||
|
label-class="text-teal"
|
||||||
|
label-style="font-size: 1.1em"
|
||||||
|
/>
|
||||||
|
<div class="colums">
|
||||||
<div class="row justify-end">
|
<div class="row justify-end">
|
||||||
<div class="column">
|
<q-btn-dropdown
|
||||||
<DateDaySelect title="hjgjh" />
|
ref="dropdownRef"
|
||||||
</div>
|
class="q-ma-sm"
|
||||||
|
color="primary"
|
||||||
|
:label="$t('selectDates')"
|
||||||
|
@show="loadSettings"
|
||||||
|
>
|
||||||
|
<DateDaySelect @update:dates="updateReport" />
|
||||||
|
<div class="column justify-end q-pa-md">
|
||||||
|
<div class="row q-ma-md">
|
||||||
|
<q-input
|
||||||
|
class="col-7"
|
||||||
|
label-color="primary"
|
||||||
|
:label="$t('filterEventName')"
|
||||||
|
:hint="$t('hintFilterEventName')"
|
||||||
|
type="text"
|
||||||
|
v-model:model-value="filter"
|
||||||
|
></q-input>
|
||||||
|
</div>
|
||||||
|
<div class="row q-ma-md">
|
||||||
|
<q-select
|
||||||
|
class="col-7"
|
||||||
|
:label="$t('filterByColumnValue')"
|
||||||
|
dense
|
||||||
|
v-model="group"
|
||||||
|
:options="groups"
|
||||||
|
option-label="name"
|
||||||
|
option-value="id"
|
||||||
|
multiple
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-end">
|
||||||
|
<q-btn dense class="q-ma-md" color="primary" no-caps @click="applyDateChoice">{{
|
||||||
|
$t('apply')
|
||||||
|
}}</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-center q-ma-xs">
|
||||||
|
<h3 class="col-12 text-center text-primary text-bold">{{ $t('report') }}</h3>
|
||||||
|
<ReportStat :amounts="amounts" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-center">
|
||||||
|
<div
|
||||||
|
v-if="attendees !== undefined"
|
||||||
|
:class="
|
||||||
|
nonAttendees !== undefined ? 'col-12 col-sm-5 col-md-5 q-pa-md' : 'col-12 col-md-8 col-lg-5'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-table
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
:no-data-label="$t('noDataAvailable')"
|
||||||
|
:loading-label="$t('loading')"
|
||||||
|
:rows-per-page-label="$t('recordsPerPage')"
|
||||||
|
:rows-per-page-options="[0]"
|
||||||
|
:title="$t('attendees')"
|
||||||
|
title-class="text-bold text-primary"
|
||||||
|
:rows="attendees"
|
||||||
|
:columns="columns"
|
||||||
|
>
|
||||||
|
</q-table>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="nonAttendees !== undefined"
|
||||||
|
:class="
|
||||||
|
attendees !== undefined ? 'col-12 col-sm-5 col-md-5 q-pa-md' : 'col-12 col-md-8 col-lg-5'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-table
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
:title="$t('noneAttendees')"
|
||||||
|
:no-data-label="$t('noDataAvailable')"
|
||||||
|
:loading-label="$t('loading')"
|
||||||
|
:rows-per-page-label="$t('recordsPerPage')"
|
||||||
|
:rows-per-page-options="[0]"
|
||||||
|
title-class="text-bold text-primary"
|
||||||
|
:rows="nonAttendees"
|
||||||
|
:columns="columns"
|
||||||
|
>
|
||||||
|
</q-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-btn @click="openDateSelect">Hallo</q-btn>
|
|
||||||
<DialogFrame :header-title="$t('selectDates')" :width="350" :height="500" ref="dateSelect">
|
|
||||||
<DateDaySelect :title="$t('selectDates')" />
|
|
||||||
<q-btn color="primary" no-caps>{{ $t('apply') }}</q-btn>
|
|
||||||
</DialogFrame>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { appApi } from 'src/boot/axios';
|
import { appApi } from 'src/boot/axios';
|
||||||
import DateDaySelect from 'src/components/DateDaySelect.vue';
|
import DateDaySelect from 'src/components/DateDaySelect.vue';
|
||||||
import { onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { useNotify } from 'src/vueLib/general/useNotify';
|
import { useNotify } from 'src/vueLib/general/useNotify';
|
||||||
import DialogFrame from 'src/vueLib/dialog/DialogFrame.vue';
|
import { i18n } from 'src/boot/lang';
|
||||||
|
import { databaseName } from 'src/vueLib/models/settings';
|
||||||
|
import type { Amount } from 'src/vueLib/models/report';
|
||||||
|
import ReportStat from 'src/components/ReportStat.vue';
|
||||||
|
import type { Group, Groups } from 'src/vueLib/models/group';
|
||||||
|
import { getLocalPageDefaults, setLocalPageDefaults } from 'src/localstorage/localStorage';
|
||||||
|
|
||||||
const dateSelect = ref();
|
const filter = ref<string>('');
|
||||||
|
const group = ref<Group[]>([]);
|
||||||
|
const groups = ref<Groups>([]);
|
||||||
|
const allDates = ref<string[]>([]);
|
||||||
|
const attendees = ref();
|
||||||
|
const nonAttendees = ref();
|
||||||
const { NotifyResponse } = useNotify();
|
const { NotifyResponse } = useNotify();
|
||||||
|
const dropdownRef = ref();
|
||||||
|
const loading = ref(false);
|
||||||
|
const amounts = ref<Amount[]>([]);
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
name: 'firstName',
|
||||||
|
align: 'left' as const,
|
||||||
|
label: i18n.global.t('prename'),
|
||||||
|
field: 'firstName',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'lastName',
|
||||||
|
align: 'left' as const,
|
||||||
|
label: i18n.global.t('lastName'),
|
||||||
|
field: 'lastName',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
loading.value = true;
|
||||||
appApi
|
appApi
|
||||||
.get('events')
|
.post('database/open', { dbPath: databaseName.value })
|
||||||
.then((resp) => console.log(1, resp))
|
.catch((err) => NotifyResponse(err, 'error'))
|
||||||
.catch((err) => NotifyResponse(err, 'error'));
|
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
appApi
|
||||||
|
.get('/groups')
|
||||||
|
.then((resp) => (groups.value = resp.data))
|
||||||
|
.catch((err) => NotifyResponse(err, 'error'))
|
||||||
|
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function openDateSelect() {
|
function loadSettings() {
|
||||||
dateSelect.value?.open();
|
const settings = getLocalPageDefaults('report');
|
||||||
|
if (!settings) return;
|
||||||
|
if (settings.filteredValues.length > 0) {
|
||||||
|
group.value = JSON.parse(settings?.filteredValues[0] || '') as Groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function applyDateChoice() {
|
||||||
|
loading.value = true;
|
||||||
|
dropdownRef.value.hide();
|
||||||
|
|
||||||
|
const payload: { name: null | string[]; date: string[]; groupIds: number[] | null } = {
|
||||||
|
name: null,
|
||||||
|
date: allDates.value,
|
||||||
|
groupIds: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter.value) {
|
||||||
|
//name is a array of string and search works as example Test*, Ge*, *st
|
||||||
|
payload.name = [filter.value];
|
||||||
|
}
|
||||||
|
if (group.value) {
|
||||||
|
// group has to be array of id numbers
|
||||||
|
payload.groupIds = group.value.map((g) => g.id);
|
||||||
|
}
|
||||||
|
payload.date = allDates.value;
|
||||||
|
|
||||||
|
setLocalPageDefaults('report', filter.value || '', [JSON.stringify(group.value || '')]);
|
||||||
|
|
||||||
|
appApi
|
||||||
|
.post('report', payload)
|
||||||
|
.then((resp) => {
|
||||||
|
attendees.value = [];
|
||||||
|
nonAttendees.value = [];
|
||||||
|
if (!resp.data) return;
|
||||||
|
if (resp.data.data === undefined) return;
|
||||||
|
const data = resp.data.data;
|
||||||
|
if (data.data === undefined) return;
|
||||||
|
|
||||||
|
if (data.attendees) {
|
||||||
|
attendees.value = data.attendees;
|
||||||
|
}
|
||||||
|
if (data.attendees) {
|
||||||
|
nonAttendees.value = data.nonAttendees;
|
||||||
|
}
|
||||||
|
|
||||||
|
const days = [
|
||||||
|
'Monday',
|
||||||
|
'Tuesday',
|
||||||
|
'Wednesday',
|
||||||
|
'Thursday',
|
||||||
|
'Friday',
|
||||||
|
'Saturday',
|
||||||
|
'Sunday',
|
||||||
|
'total',
|
||||||
|
];
|
||||||
|
amounts.value = days
|
||||||
|
.filter((day) => data.data[day]) // Only include days that exist in the response
|
||||||
|
.map((day) => ({
|
||||||
|
...data.data[day],
|
||||||
|
name: i18n.global.t(day), // Dynamically translate the name
|
||||||
|
}));
|
||||||
|
if (amounts.value.length == 2) {
|
||||||
|
amounts.value.splice(1);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => NotifyResponse(err, 'error'))
|
||||||
|
.finally(() => (loading.value = false));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateReport(dates: string[]) {
|
||||||
|
allDates.value = dates;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
7
src/vueLib/models/report.ts
Normal file
7
src/vueLib/models/report.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export type Amount = {
|
||||||
|
name: string;
|
||||||
|
events: number;
|
||||||
|
minimal: number;
|
||||||
|
average: number;
|
||||||
|
maximal: number;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user