change whole backend and tables for gorm table references

simplify tables with table components close #31
This commit is contained in:
Adrian Zürcher
2025-11-29 15:59:18 +01:00
parent 62549c9039
commit bdcceb53e0
29 changed files with 646 additions and 514 deletions

View File

@@ -6,6 +6,10 @@ import { i18n } from 'boot/lang';
import { useResponsibleTable } from '../responsible/ResponsibleTable';
import { appName } from 'src/vueLib/models/settings';
import { useGroupTable } from '../group/GroupTable';
import IconComponent from '../components/IconComponent.vue';
import SearchableSelectComponent from '../components/SearchableSelect.vue';
import ClickableComponent from '../components/ClickableComponent.vue';
import MenuComponent from '../components/MenuComponent.vue';
export function useMemberTable() {
const allMembers = ref<Members>([]);
@@ -16,7 +20,7 @@ export function useMemberTable() {
keys: string[];
}[]
>();
const { responsibles, updateResponsibles } = useResponsibleTable();
const { responsibles, responsibleMember, updateResponsibles } = useResponsibleTable();
const { groups, updateGroups } = useGroupTable();
const pagination = ref({
@@ -40,21 +44,30 @@ export function useMemberTable() {
phone: true,
email: true,
group: true,
responsiblePerson: true,
responsible: true,
firstVisit: true,
lastVisit: true,
option: true,
test: true,
});
const columns = computed(() =>
[
{ name: 'cake', align: 'center' as const, label: '', field: 'cake', icon: 'cake' },
{
name: 'cake',
align: 'center' as const,
label: '',
field: 'cake',
icon: 'cake',
component: IconComponent,
},
{
name: 'firstName',
align: 'left' as const,
label: i18n.global.t('prename'),
field: 'firstName',
sortable: true,
component: ClickableComponent,
},
{
name: 'lastName',
@@ -62,6 +75,7 @@ export function useMemberTable() {
label: i18n.global.t('lastName'),
field: 'lastName',
sortable: true,
component: ClickableComponent,
},
{
name: 'birthday',
@@ -69,6 +83,7 @@ export function useMemberTable() {
label: i18n.global.t('birthday'),
field: 'birthday',
sortable: true,
component: ClickableComponent,
},
{
name: 'age',
@@ -76,6 +91,7 @@ export function useMemberTable() {
label: i18n.global.t('age'),
field: 'age',
sortable: true,
component: ClickableComponent,
},
{
name: 'comment',
@@ -83,6 +99,7 @@ export function useMemberTable() {
label: i18n.global.t('comment'),
field: 'comment',
sortable: true,
component: ClickableComponent,
},
{
name: 'address',
@@ -90,6 +107,7 @@ export function useMemberTable() {
label: i18n.global.t('address'),
field: 'address',
sortable: true,
component: ClickableComponent,
},
{
name: 'town',
@@ -97,6 +115,7 @@ export function useMemberTable() {
label: i18n.global.t('town'),
field: 'town',
sortable: true,
component: ClickableComponent,
},
{
name: 'zip',
@@ -104,6 +123,7 @@ export function useMemberTable() {
label: i18n.global.t('zipCode'),
field: 'zip',
sortable: true,
component: ClickableComponent,
},
{
name: 'phone',
@@ -111,6 +131,7 @@ export function useMemberTable() {
label: i18n.global.t('phone'),
field: 'phone',
sortable: true,
component: ClickableComponent,
},
{
name: 'email',
@@ -118,6 +139,7 @@ export function useMemberTable() {
label: i18n.global.t('email'),
field: 'email',
sortable: true,
component: ClickableComponent,
},
{
name: 'group',
@@ -125,13 +147,15 @@ export function useMemberTable() {
label: i18n.global.t('group'),
field: 'group',
sortable: true,
component: SearchableSelectComponent,
},
{
name: 'responsiblePerson',
name: 'responsible',
align: 'left' as const,
label: i18n.global.t('responsible'),
field: 'responsiblePerson',
field: 'responsible',
sortable: true,
component: SearchableSelectComponent,
},
{
name: 'firstVisit',
@@ -139,6 +163,7 @@ export function useMemberTable() {
label: i18n.global.t('firstVisit'),
field: 'firstVisit',
sortable: true,
component: ClickableComponent,
},
{
name: 'lastVisit',
@@ -146,8 +171,16 @@ export function useMemberTable() {
label: i18n.global.t('lastVisit'),
field: 'lastVisit',
sortable: true,
component: ClickableComponent,
},
{
name: 'option',
align: 'center' as const,
label: '',
field: 'option',
icon: 'option',
component: MenuComponent,
},
{ name: 'option', align: 'center' as const, label: '', field: 'option', icon: 'option' },
].filter((c) => enabledColumns.value[c.name]),
);
@@ -225,11 +258,13 @@ export function useMemberTable() {
return;
}
allMembers.value.forEach((member) => {
if (!responsibles.value.some((r) => r.id === member.responsiblePerson?.id)) {
delete member.responsiblePerson;
// remove responsible of member if it does not exist in responsible list any longer
if (!responsibles.value.some((r) => r.id === member.responsible?.id)) {
delete member.responsible;
}
if (member.birthday !== undefined) {
//calculte years if a birth date is entered
if (member.birthday) {
member.age = String(calculateAge(member.birthday));
}
});
@@ -314,9 +349,14 @@ export function useMemberTable() {
exportableColumns
.map((col) => {
const value = member[col.field];
// handle nested objects (e.g. responsiblePerson)
// handle nested objects (e.g. responsible)
if (typeof value === 'object' && value !== null) {
if ('firstName' in value && 'lastName' in value)
if (
'firstName' in value &&
'lastName' in value &&
typeof value.firstName === 'string' &&
typeof value.lastName === 'string'
)
return `"${value.firstName} ${value.lastName}"`;
return `"${JSON.stringify(value)}"`;
}
@@ -344,6 +384,7 @@ export function useMemberTable() {
allMembers,
filteredMembers,
responsibles,
responsibleMember,
groups,
pagination,
columns,