98 lines
2.4 KiB
Vue
98 lines
2.4 KiB
Vue
|
<script setup>
|
||
|
import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
|
||
|
import { useI18n } from 'vue-i18n';
|
||
|
import { useQuasar } from 'quasar';
|
||
|
import axios from 'axios';
|
||
|
|
||
|
import { useState } from 'src/composables/useState';
|
||
|
import SkeletonForm from 'src/components/SkeletonForm.vue';
|
||
|
|
||
|
const quasar = useQuasar();
|
||
|
const { t } = useI18n();
|
||
|
const state = useState();
|
||
|
|
||
|
const $props = defineProps({
|
||
|
url: {
|
||
|
type: String,
|
||
|
default: '',
|
||
|
},
|
||
|
model: {
|
||
|
type: String,
|
||
|
default: '',
|
||
|
},
|
||
|
filter: {
|
||
|
type: Object,
|
||
|
default: null,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const emit = defineEmits(['fetch-data']);
|
||
|
|
||
|
defineExpose({
|
||
|
save,
|
||
|
});
|
||
|
|
||
|
onMounted(async () => await fetch());
|
||
|
|
||
|
onUnmounted(() => {
|
||
|
state.unset($props.model);
|
||
|
});
|
||
|
|
||
|
const isLoading = ref(false);
|
||
|
const hasChanges = ref(false);
|
||
|
const formData = computed(() => state.get($props.model));
|
||
|
const originalData = ref();
|
||
|
|
||
|
async function fetch() {
|
||
|
const { data } = await axios.get($props.url, {
|
||
|
params: { filter: $props.filter },
|
||
|
});
|
||
|
|
||
|
state.set($props.model, data);
|
||
|
originalData.value = Object.assign({}, data);
|
||
|
|
||
|
watch(formData.value, () => (hasChanges.value = true));
|
||
|
|
||
|
return emit('fetch-data', state.get($props.model));
|
||
|
}
|
||
|
|
||
|
async function save() {
|
||
|
if (!hasChanges.value) {
|
||
|
return quasar.notify({
|
||
|
type: 'negative',
|
||
|
message: t('globals.noChanges'),
|
||
|
});
|
||
|
}
|
||
|
isLoading.value = true;
|
||
|
await new Promise((resolve) => {
|
||
|
setTimeout(resolve, 5000);
|
||
|
});
|
||
|
await axios.patch($props.url, formData.value);
|
||
|
isLoading.value = false;
|
||
|
}
|
||
|
|
||
|
function reset() {
|
||
|
state.set($props.model, originalData.value);
|
||
|
hasChanges.value = false;
|
||
|
}
|
||
|
</script>
|
||
|
<template>
|
||
|
<q-banner v-if="hasChanges" inline-actions class="text-white bg-red"> You have changes pending to save </q-banner>
|
||
|
<q-form v-if="formData" @submit="save" @reset="reset" class="q-pa-md">
|
||
|
<slot name="form" :data="formData"></slot>
|
||
|
<slot name="actions">
|
||
|
<q-btn :label="t('globals.save')" type="submit" color="primary" />
|
||
|
<q-btn
|
||
|
:label="t('globals.reset')"
|
||
|
type="reset"
|
||
|
class="q-ml-sm"
|
||
|
color="primary"
|
||
|
flat
|
||
|
:disable="!hasChanges"
|
||
|
/>
|
||
|
</slot>
|
||
|
</q-form>
|
||
|
<skeleton-form v-if="!formData" />
|
||
|
<q-inner-loading :showing="isLoading" :label="t('globals.pleaseWait')" color="primary" />
|
||
|
</template>
|