vikunja/frontend/src/components/misc/CreateEdit.vue

113 lines
2.2 KiB
Vue

<template>
<Modal
:overflow="true"
:wide="wide"
@close="$router.back()"
>
<Card
:title="title"
:shadow="false"
:padding="false"
class="has-text-start"
:loading="currentLoading"
:show-close="true"
@close="$router.back()"
>
<div class="p-4">
<slot />
</div>
<template #footer>
<slot name="footer">
<XButton
v-if="tertiary !== ''"
:shadow="false"
variant="tertiary"
@click.prevent.stop="$emit('tertiary', $event)"
>
{{ tertiary }}
</XButton>
<XButton
variant="secondary"
@click.prevent.stop="$router.back()"
>
{{ $t('misc.cancel') }}
</XButton>
<XButton
v-if="hasPrimaryAction"
variant="primary"
:icon="primaryIcon"
:disabled="isBusy"
class="mis-2"
:loading="currentLoading"
@click.prevent.stop="primary"
>
{{ primaryLabel || $t('misc.create') }}
</XButton>
</slot>
</template>
</Card>
</Modal>
</template>
<script setup lang="ts">
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import {computed, ref, toRef, watch} from 'vue'
const props = withDefaults(defineProps<{
title: string,
primaryLabel?: string,
primaryIcon?: IconProp,
primaryDisabled?: boolean,
hasPrimaryAction?: boolean,
tertiary?: string,
wide?: boolean,
loading?: boolean,
}>(), {
primaryLabel: '',
primaryIcon: 'plus',
primaryDisabled: false,
hasPrimaryAction: true,
tertiary: '',
wide: false,
})
const emit = defineEmits<{
'create': [event: MouseEvent],
'primary': [event: MouseEvent],
'tertiary': [event: MouseEvent],
'update:loading': [value: boolean],
}>()
const loadingProp = toRef(props, 'loading')
const currentLoading = ref(false)
watch(
loadingProp,
(value) => {
if (value !== undefined) {
currentLoading.value = value
}
},
{immediate: true},
)
const isBusy = computed(() => props.primaryDisabled || currentLoading.value)
function setLoading(value: boolean) {
currentLoading.value = value
emit('update:loading', value)
}
function primary(event: MouseEvent) {
if (isBusy.value) {
return
}
emit('create', event)
emit('primary', event)
setLoading(true)
}
</script>