|
|
@@ -1,5 +1,7 @@
|
|
|
<template>
|
|
|
- <div class="q-pa-md column q-gutter-lg">
|
|
|
+ <div class="q-pa-md">
|
|
|
+ <q-scroll-area ref="scrollAreaRef" class="unit-form-tab-scroll-area">
|
|
|
+ <DefaultForm ref="formRef" class="column q-gutter-lg" @submit="onSave">
|
|
|
<!-- Dados Bancários -->
|
|
|
<div>
|
|
|
<div class="text-subtitle1 text-weight-medium q-mb-sm">
|
|
|
@@ -9,18 +11,24 @@
|
|
|
<div class="row q-col-gutter-sm">
|
|
|
<DefaultInput
|
|
|
v-model="form.account_holder"
|
|
|
+ v-model:error="validationErrors.account_holder"
|
|
|
+ :error-message="validationErrors.account_holder"
|
|
|
label="Titular da Conta"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model="form.agency"
|
|
|
+ v-model:error="validationErrors.agency"
|
|
|
+ :error-message="validationErrors.agency"
|
|
|
label="Agência"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model="form.account"
|
|
|
+ v-model:error="validationErrors.account"
|
|
|
+ :error-message="validationErrors.account"
|
|
|
label="Conta"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
@@ -28,18 +36,24 @@
|
|
|
|
|
|
<DefaultInput
|
|
|
v-model="form.bank"
|
|
|
+ v-model:error="validationErrors.bank"
|
|
|
+ :error-message="validationErrors.bank"
|
|
|
label="Banco"
|
|
|
class="col-12 col-md-3"
|
|
|
outlined
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model="form.pix_key"
|
|
|
+ v-model:error="validationErrors.pix_key"
|
|
|
+ :error-message="validationErrors.pix_key"
|
|
|
label="Chave Pix"
|
|
|
class="col-12 col-md-3"
|
|
|
outlined
|
|
|
/>
|
|
|
<DefaultSelect
|
|
|
v-model="form.tax_regime"
|
|
|
+ v-model:error="validationErrors.tax_regime"
|
|
|
+ :error-message="validationErrors.tax_regime"
|
|
|
label="Regime Tributário"
|
|
|
:options="taxRegimeOptions"
|
|
|
class="col-12 col-md-3"
|
|
|
@@ -49,6 +63,8 @@
|
|
|
/>
|
|
|
<DefaultSelect
|
|
|
v-model="form.account_type"
|
|
|
+ v-model:error="validationErrors.account_type"
|
|
|
+ :error-message="validationErrors.account_type"
|
|
|
label="Tipo de Conta"
|
|
|
:options="accountTypeOptions"
|
|
|
class="col-12 col-md-3"
|
|
|
@@ -68,6 +84,8 @@
|
|
|
<div class="row q-col-gutter-sm">
|
|
|
<DefaultSelect
|
|
|
v-model="form.billing_method"
|
|
|
+ v-model:error="validationErrors.billing_method"
|
|
|
+ :error-message="validationErrors.billing_method"
|
|
|
label="Forma de Cobrança"
|
|
|
:options="billingMethodOptions"
|
|
|
class="col-12 col-md-6"
|
|
|
@@ -77,14 +95,19 @@
|
|
|
/>
|
|
|
<DefaultInputDatePicker
|
|
|
v-model="form.due_date"
|
|
|
+ v-model:error="validationErrors.due_date"
|
|
|
+ :error-message="validationErrors.due_date"
|
|
|
label="Data de Vencimento"
|
|
|
class="col-12 col-md-6"
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model="form.financial_email"
|
|
|
+ v-model:error="validationErrors.financial_email"
|
|
|
+ :error-message="validationErrors.financial_email"
|
|
|
label="E-mail Financeiro"
|
|
|
class="col-12"
|
|
|
outlined
|
|
|
+ :rules="[inputRules.email]"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -98,31 +121,43 @@
|
|
|
<div class="row q-col-gutter-sm">
|
|
|
<DefaultInput
|
|
|
v-model.number="form.max_freeze_count"
|
|
|
+ v-model:error="validationErrors.max_freeze_count"
|
|
|
+ :error-message="validationErrors.max_freeze_count"
|
|
|
label="Máximo de Meses para Trancar"
|
|
|
type="number"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
+ :rules="[inputRules.minValue(0)]"
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model.number="form.default_discount"
|
|
|
+ v-model:error="validationErrors.default_discount"
|
|
|
+ :error-message="validationErrors.default_discount"
|
|
|
label="Desconto Padrão (%)"
|
|
|
type="number"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
+ :rules="[inputRules.minValue(0), inputRules.maxValue(100)]"
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model.number="form.default_interest"
|
|
|
+ v-model:error="validationErrors.default_interest"
|
|
|
+ :error-message="validationErrors.default_interest"
|
|
|
label="Juros Padrão (% a.m.)"
|
|
|
type="number"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
+ :rules="[inputRules.minValue(0)]"
|
|
|
/>
|
|
|
<DefaultInput
|
|
|
v-model.number="form.default_fine"
|
|
|
+ v-model:error="validationErrors.default_fine"
|
|
|
+ :error-message="validationErrors.default_fine"
|
|
|
label="Multa Padrão (%)"
|
|
|
type="number"
|
|
|
class="col-12 col-md-4"
|
|
|
outlined
|
|
|
+ :rules="[inputRules.minValue(0), inputRules.maxValue(100)]"
|
|
|
/>
|
|
|
<div class="col-12 col-md-4 flex items-center">
|
|
|
<q-toggle v-model="form.charge_roi" label="Cobrar ROI" color="primary" />
|
|
|
@@ -139,10 +174,12 @@
|
|
|
<q-btn
|
|
|
label="Salvar"
|
|
|
color="primary-2"
|
|
|
- :loading="saving"
|
|
|
- @click="onSave"
|
|
|
+ type="submit"
|
|
|
+ :loading="loading"
|
|
|
/>
|
|
|
</div>
|
|
|
+ </DefaultForm>
|
|
|
+ </q-scroll-area>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -152,6 +189,10 @@ import DefaultInput from "src/components/defaults/DefaultInput.vue";
|
|
|
import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
|
|
|
import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
|
|
|
import { getFinancialByUnit, upsertFinancial } from "src/api/unit_financial";
|
|
|
+import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
+import { useInputRules } from "src/composables/useInputRules";
|
|
|
+import { useScroll } from "src/composables/useScroll";
|
|
|
+import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
|
|
|
|
const props = defineProps({
|
|
|
unitId: { type: Number, default: null },
|
|
|
@@ -198,10 +239,12 @@ const defaultForm = () => ({
|
|
|
default_fine: null,
|
|
|
});
|
|
|
|
|
|
-const form = ref(defaultForm());
|
|
|
-const saving = ref(false);
|
|
|
-
|
|
|
-let originalForm = defaultForm();
|
|
|
+const formRef = ref(null);
|
|
|
+const scrollAreaRef = ref(null);
|
|
|
+const { inputRules } = useInputRules();
|
|
|
+const { scrollToComponent } = useScroll();
|
|
|
+const { form, getUpdatedFields, resetUpdateForm, setUpdateFormAsOriginal } =
|
|
|
+ useFormUpdateTracker(defaultForm(), { containerRef: scrollAreaRef });
|
|
|
|
|
|
async function fetchData() {
|
|
|
if (!props.unitId) return;
|
|
|
@@ -212,34 +255,44 @@ async function loadFinancial() {
|
|
|
try {
|
|
|
const data = await getFinancialByUnit(props.unitId);
|
|
|
if (data) {
|
|
|
- Object.assign(form.value, data);
|
|
|
- originalForm = { ...data };
|
|
|
+ Object.assign(form, data);
|
|
|
+ setUpdateFormAsOriginal();
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error(e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const { loading, validationErrors, execute } = useSubmitHandler({
|
|
|
+ formRef,
|
|
|
+ containerRef: scrollAreaRef,
|
|
|
+ scrollFn: scrollToComponent,
|
|
|
+ onSuccess: (saved) => {
|
|
|
+ Object.assign(form, saved);
|
|
|
+ setUpdateFormAsOriginal();
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
async function onSave() {
|
|
|
if (!props.unitId) return;
|
|
|
- saving.value = true;
|
|
|
- try {
|
|
|
- const saved = await upsertFinancial({
|
|
|
+ await execute(() =>
|
|
|
+ upsertFinancial({
|
|
|
unit_id: props.unitId,
|
|
|
- ...form.value,
|
|
|
- });
|
|
|
- Object.assign(form.value, saved);
|
|
|
- originalForm = { ...saved };
|
|
|
- } catch (e) {
|
|
|
- console.error(e);
|
|
|
- } finally {
|
|
|
- saving.value = false;
|
|
|
- }
|
|
|
+ ...getUpdatedFields.value,
|
|
|
+ }),
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
function resetForm() {
|
|
|
- Object.assign(form.value, defaultForm(), originalForm);
|
|
|
+ resetUpdateForm();
|
|
|
}
|
|
|
|
|
|
onMounted(fetchData);
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.unit-form-tab-scroll-area {
|
|
|
+ height: calc(100vh - 280px);
|
|
|
+ min-height: 320px;
|
|
|
+}
|
|
|
+</style>
|