Added IBAN Saving, Automatic Saving, added Mitglieder
Some checks failed
Build and Push Docker Images / build-backend (push) Failing after 1m25s
Build and Push Docker Images / build-frontend (push) Failing after 38s

This commit is contained in:
2026-02-16 12:40:07 +01:00
parent 3f8ce5daf7
commit 189a52b3cd
14 changed files with 879 additions and 22 deletions

View File

@@ -69,20 +69,31 @@ generateOldItemData()
const saveAllowed = computed(() => {
if (!item.value) return false
const isFilledValue = (value) => {
if (Array.isArray(value)) return value.length > 0
if (typeof value === "string") return value.trim().length > 0
return value !== null && value !== undefined && value !== false
}
let allowedCount = 0
// Nur Input-Felder berücksichtigen
const relevantColumns = dataType.templateColumns.filter(i => i.inputType)
const relevantColumns = dataType.templateColumns.filter(i => {
if (!i.inputType) return false
if (i.showFunction && !i.showFunction(item.value)) return false
if (i.disabledFunction && i.disabledFunction(item.value)) return false
return true
})
relevantColumns.forEach(datapoint => {
if(datapoint.required) {
if(datapoint.key.includes(".")){
const [parentKey, childKey] = datapoint.key.split('.')
// Prüfung: Existiert Parent UND ist Child "truthy" (nicht null/undefined/empty)
if(item.value[parentKey] && item.value[parentKey][childKey]) {
if(item.value[parentKey] && isFilledValue(item.value[parentKey][childKey])) {
allowedCount += 1
}
} else {
if(item.value[datapoint.key]) {
if(isFilledValue(item.value[datapoint.key])) {
allowedCount += 1
}
}
@@ -427,6 +438,11 @@ const updateItem = async () => {
/>
</template>
</UPopover>
<BankAccountAssignInput
v-else-if="datapoint.inputType === 'bankaccountassign'"
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
/>
<Tiptap
v-else-if="datapoint.inputType === 'editor'"
@updateContent="(i) => contentChanged(i,datapoint)"
@@ -527,6 +543,11 @@ const updateItem = async () => {
/>
</template>
</UPopover>
<BankAccountAssignInput
v-else-if="datapoint.inputType === 'bankaccountassign'"
v-model="item[datapoint.key]"
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
/>
<Tiptap
v-else-if="datapoint.inputType === 'editor'"
@updateContent="(i) => contentChanged(i,datapoint)"
@@ -652,6 +673,11 @@ const updateItem = async () => {
/>
</template>
</UPopover>
<BankAccountAssignInput
v-else-if="datapoint.inputType === 'bankaccountassign'"
v-model="item[datapoint.key.split('.')[0]][datapoint.key.split('.')[1]]"
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
/>
<Tiptap
v-else-if="datapoint.inputType === 'editor'"
@updateContent="(i) => contentChanged(i,datapoint)"
@@ -752,6 +778,11 @@ const updateItem = async () => {
/>
</template>
</UPopover>
<BankAccountAssignInput
v-else-if="datapoint.inputType === 'bankaccountassign'"
v-model="item[datapoint.key]"
:disabled="datapoint.disabledFunction ? datapoint.disabledFunction(item) : false"
/>
<Tiptap
v-else-if="datapoint.inputType === 'editor'"
@updateContent="(i) => contentChanged(i,datapoint)"
@@ -788,4 +819,4 @@ td {
padding-bottom: 0.15em;
padding-top: 0.15em;
}
</style>
</style>

View File

@@ -69,6 +69,12 @@ const profileStore = useProfileStore()
const tempStore = useTempStore()
const dataType = dataStore.dataTypes[type]
const canCreate = computed(() => {
if (type === "members") {
return has("members-create") || has("customers-create")
}
return has(`${type}-create`)
})
const selectedColumns = ref(tempStore.columns[type] ? tempStore.columns[type] : dataType.templateColumns.filter(i => !i.disabledInTable))
const columns = computed(() => dataType.templateColumns.filter((column) => !column.disabledInTable && selectedColumns.value.find(i => i.key === column.key)))
@@ -138,7 +144,7 @@ const filteredRows = computed(() => {
/>
<UButton
v-if="platform !== 'mobile' && has(`${type}-create`)/*&& useRole().checkRight(`${type}-create`)*/"
v-if="platform !== 'mobile' && canCreate/*&& useRole().checkRight(`${type}-create`)*/"
@click="router.push(`/standardEntity/${type}/create`)"
class="ml-3"
>+ {{dataType.labelSingle}}</UButton>
@@ -200,4 +206,4 @@ const filteredRows = computed(() => {
<style scoped>
</style>
</style>

View File

@@ -69,7 +69,7 @@ const getAvailableQueryStringData = (keys) => {
if(props.item.customer) {
addParam("customer", props.item.customer.id)
} else if(type === "customers") {
} else if(type === "customers" || type === "members") {
addParam("customer", props.item.id)
}
@@ -372,4 +372,4 @@ const changePinned = async () => {
<style scoped>
</style>
</style>

View File

@@ -5,6 +5,13 @@ const { has } = usePermission()
// Lokaler State für den Taschenrechner
const showCalculator = ref(false)
const tenantExtraModules = computed(() => {
const modules = auth.activeTenantData?.extraModules
return Array.isArray(modules) ? modules : []
})
const showMembersNav = computed(() => {
return tenantExtraModules.value.includes("verein") && (has("members") || has("customers"))
})
const links = computed(() => {
return [
@@ -98,11 +105,16 @@ const links = computed(() => {
}
]
},
...(has("customers") || has("vendors") || has("contacts")) ? [{
...(has("customers") || has("vendors") || has("contacts") || showMembersNav.value) ? [{
label: "Kontakte",
defaultOpen: false,
icon: "i-heroicons-user-group",
children: [
...showMembersNav.value ? [{
label: "Mitglieder",
to: "/standardEntity/members",
icon: "i-heroicons-user-group"
}] : [],
...has("customers") ? [{
label: "Kunden",
to: "/standardEntity/customers",