|
@@ -0,0 +1,255 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
|
|
+ <q-card class="q-dialog-plugin overflow-hidden" style="width: 900px; max-width: 90vw">
|
|
|
|
|
+ <DefaultDialogHeader :title="title" @close="onDialogCancel" />
|
|
|
|
|
+ <q-form ref="formRef" @submit="onOKClick">
|
|
|
|
|
+ <q-card-section class="row q-col-gutter-sm">
|
|
|
|
|
+ <UserSelect
|
|
|
|
|
+ v-model="selectedUser"
|
|
|
|
|
+ :label="$t('common.terms.user')"
|
|
|
|
|
+ :rules="[inputRules.required]"
|
|
|
|
|
+ :error="!!serverErrors?.user_id"
|
|
|
|
|
+ :error-message="serverErrors?.user_id"
|
|
|
|
|
+ :initial-id="provider ? provider.user_id : null"
|
|
|
|
|
+ class="col-md-6 col-12"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <q-input
|
|
|
|
|
+ v-model="form.document"
|
|
|
|
|
+ :mask="documentMask"
|
|
|
|
|
+ fill-mask
|
|
|
|
|
+ unmasked-value
|
|
|
|
|
+ :label="$t('provider.fields.document')"
|
|
|
|
|
+ :rules="[inputRules.required, validateDocument]"
|
|
|
|
|
+ :error="!!serverErrors?.document"
|
|
|
|
|
+ :error-message="serverErrors?.document"
|
|
|
|
|
+ class="col-md-6 col-12"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <q-input
|
|
|
|
|
+ v-model="form.rg"
|
|
|
|
|
+ mask="##.###.###-#"
|
|
|
|
|
+ fill-mask
|
|
|
|
|
+ :label="$t('provider.fields.rg')"
|
|
|
|
|
+ :error="!!serverErrors?.rg"
|
|
|
|
|
+ :error-message="serverErrors?.rg"
|
|
|
|
|
+ class="col-md-6 col-12"
|
|
|
|
|
+ />
|
|
|
|
|
+ <DefaultInputDatePicker
|
|
|
|
|
+ v-model:untreated-date="form.birth_date"
|
|
|
|
|
+ :label="$t('provider.fields.birth_date')"
|
|
|
|
|
+ :error="serverErrors?.birth_date"
|
|
|
|
|
+ :error-message="serverErrors?.birth_date"
|
|
|
|
|
+ class="col-md-6 col-12"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <DefaultCurrencyInput
|
|
|
|
|
+ v-model="form.daily_price_8h"
|
|
|
|
|
+ :label="$t('provider.fields.daily_price_8h')"
|
|
|
|
|
+ :error="!!serverErrors?.daily_price_8h"
|
|
|
|
|
+ :error-message="serverErrors?.daily_price_8h"
|
|
|
|
|
+ :hint="$t('provider.hints.daily_price')"
|
|
|
|
|
+ lazy-rules
|
|
|
|
|
+ class="col-md-3 col-6"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <DefaultCurrencyInput
|
|
|
|
|
+ v-model="form.daily_price_6h"
|
|
|
|
|
+ :label="$t('provider.fields.daily_price_6h')"
|
|
|
|
|
+ :error="!!serverErrors?.daily_price_6h"
|
|
|
|
|
+ :error-message="serverErrors?.daily_price_6h"
|
|
|
|
|
+ disable
|
|
|
|
|
+ class="col-md-3 col-6"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <DefaultCurrencyInput
|
|
|
|
|
+ v-model="form.daily_price_4h"
|
|
|
|
|
+ :label="$t('provider.fields.daily_price_4h')"
|
|
|
|
|
+ :error="!!serverErrors?.daily_price_4h"
|
|
|
|
|
+ :error-message="serverErrors?.daily_price_4h"
|
|
|
|
|
+ disable
|
|
|
|
|
+ class="col-md-3 col-6"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <DefaultCurrencyInput
|
|
|
|
|
+ v-model="form.daily_price_2h"
|
|
|
|
|
+ :label="$t('provider.fields.daily_price_2h')"
|
|
|
|
|
+ :error="!!serverErrors?.daily_price_2h"
|
|
|
|
|
+ :error-message="serverErrors?.daily_price_2h"
|
|
|
|
|
+ disable
|
|
|
|
|
+ class="col-md-3 col-6"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col-12">
|
|
|
|
|
+ <q-checkbox
|
|
|
|
|
+ v-model="form.is_approved"
|
|
|
|
|
+ :label="$t('provider.fields.is_approved')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col-12 q-mt-md">
|
|
|
|
|
+ <div class="row q-col-gutter-md">
|
|
|
|
|
+ <div class="col-auto flex items-center">
|
|
|
|
|
+ <q-avatar size="80px" color="grey-3">
|
|
|
|
|
+ <q-icon name="mdi-account" size="50px" color="grey-6" />
|
|
|
|
|
+ </q-avatar>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col row q-col-gutter-sm">
|
|
|
|
|
+ <div class="col-md-6 col-12">
|
|
|
|
|
+ <div class="text-subtitle2 text-grey-7">
|
|
|
|
|
+ {{ $t('provider.fields.average_rating') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="text-body1 text-weight-medium">
|
|
|
|
|
+ {{ provider?.average_rating || '-' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col-md-6 col-12">
|
|
|
|
|
+ <div class="text-subtitle2 text-grey-7">
|
|
|
|
|
+ {{ $t('provider.fields.total_services') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="text-body1 text-weight-medium">
|
|
|
|
|
+ {{ provider?.total_services || '0' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col-md-6 col-12">
|
|
|
|
|
+ <div class="text-subtitle2 text-grey-7">
|
|
|
|
|
+ {{ $t('provider.fields.selfie_verified') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="text-body1 text-weight-medium">
|
|
|
|
|
+ {{ provider?.selfie_verified ? $t('common.status.yes') : $t('common.status.no') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="col-md-6 col-12">
|
|
|
|
|
+ <div class="text-subtitle2 text-grey-7">
|
|
|
|
|
+ {{ $t('provider.fields.document_verified') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="text-body1 text-weight-medium">
|
|
|
|
|
+ {{ provider?.document_verified ? $t('common.status.yes') : $t('common.status.no') }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </q-card-section>
|
|
|
|
|
+ <q-card-actions align="center">
|
|
|
|
|
+ <q-btn color="primary" label="Cancel" @click="onDialogCancel" />
|
|
|
|
|
+ <q-space />
|
|
|
|
|
+ <q-btn
|
|
|
|
|
+ color="primary"
|
|
|
|
|
+ label="OK"
|
|
|
|
|
+ :type="'submit'"
|
|
|
|
|
+ :loading="loading"
|
|
|
|
|
+ :disable="!hasUpdatedFields"
|
|
|
|
|
+ />
|
|
|
|
|
+ </q-card-actions>
|
|
|
|
|
+ </q-form>
|
|
|
|
|
+ </q-card>
|
|
|
|
|
+ </q-dialog>
|
|
|
|
|
+</template>
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, useTemplateRef, onMounted, watch, computed } from "vue";
|
|
|
|
|
+import { useInputRules } from "src/composables/useInputRules";
|
|
|
|
|
+import { useDialogPluginComponent } from "quasar";
|
|
|
|
|
+import { useI18n } from "vue-i18n";
|
|
|
|
|
+import { createProvider, updateProvider } from "src/api/provider";
|
|
|
|
|
+import { useFormUpdateTracker } from "src/composables/useFormUpdateTracker";
|
|
|
|
|
+import { useSubmitHandler } from "src/composables/useSubmitHandler";
|
|
|
|
|
+import { dynamicCpfCnpjMask, validateCpfCnpj, calculateDailyPrices } from "src/helpers/utils";
|
|
|
|
|
+
|
|
|
|
|
+import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
|
|
|
|
|
+import UserSelect from "src/components/user/UserSelect.vue";
|
|
|
|
|
+import DefaultInputDatePicker from "src/components/defaults/DefaultInputDatePicker.vue";
|
|
|
|
|
+import DefaultCurrencyInput from "src/components/defaults/DefaultCurrencyInput.vue";
|
|
|
|
|
+
|
|
|
|
|
+defineEmits([
|
|
|
|
|
+ ...useDialogPluginComponent.emits,
|
|
|
|
|
+]);
|
|
|
|
|
+
|
|
|
|
|
+const { provider, title } = defineProps({
|
|
|
|
|
+ provider: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: null,
|
|
|
|
|
+ },
|
|
|
|
|
+ title: {
|
|
|
|
|
+ type: Function,
|
|
|
|
|
+ default: () => useI18n().t("common.terms.title"),
|
|
|
|
|
+ },
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const { t } = useI18n();
|
|
|
|
|
+const { inputRules } = useInputRules();
|
|
|
|
|
+
|
|
|
|
|
+const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
|
|
|
|
+ useDialogPluginComponent();
|
|
|
|
|
+
|
|
|
|
|
+const formRef = useTemplateRef("formRef");
|
|
|
|
|
+
|
|
|
|
|
+const { form, getUpdatedFields, hasUpdatedFields } = useFormUpdateTracker({
|
|
|
|
|
+ user_id: provider ? provider?.user_id : null,
|
|
|
|
|
+ document: provider ? provider?.document : "",
|
|
|
|
|
+ rg: provider ? provider?.rg : "",
|
|
|
|
|
+ birth_date: provider ? provider?.birth_date : null,
|
|
|
|
|
+ is_approved: provider ? provider?.is_approved : false,
|
|
|
|
|
+ daily_price_8h: provider ? Number(provider?.daily_price_8h) : null,
|
|
|
|
|
+ daily_price_6h: provider ? Number(provider?.daily_price_6h) : null,
|
|
|
|
|
+ daily_price_4h: provider ? Number(provider?.daily_price_4h) : null,
|
|
|
|
|
+ daily_price_2h: provider ? Number(provider?.daily_price_2h) : null,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// const birthDate = ref(null);
|
|
|
|
|
+
|
|
|
|
|
+const {
|
|
|
|
|
+ loading,
|
|
|
|
|
+ serverErrors,
|
|
|
|
|
+ execute: submitForm,
|
|
|
|
|
+} = useSubmitHandler({
|
|
|
|
|
+ onSuccess: () => onDialogOK(true),
|
|
|
|
|
+ formRef: formRef,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const selectedUser = ref(null);
|
|
|
|
|
+
|
|
|
|
|
+const documentMask = computed(() => {
|
|
|
|
|
+ return dynamicCpfCnpjMask(form.document);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const validateDocument = (val) => {
|
|
|
|
|
+ if (!val) return true;
|
|
|
|
|
+ return validateCpfCnpj(val) || t("validation.rules.cpf") + " / " + t("validation.rules.cnpj");
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const onOKClick = async () => {
|
|
|
|
|
+ if (provider) {
|
|
|
|
|
+ await submitForm(() => updateProvider(getUpdatedFields.value, provider.id));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await submitForm(() => createProvider({ ...form }));
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+watch(selectedUser, () => {
|
|
|
|
|
+ form.user_id = selectedUser.value?.value;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => form.daily_price_8h,
|
|
|
|
|
+ (newValue) => {
|
|
|
|
|
+ const prices = calculateDailyPrices(newValue);
|
|
|
|
|
+ form.daily_price_6h = prices.daily_price_6h;
|
|
|
|
|
+ form.daily_price_4h = prices.daily_price_4h;
|
|
|
|
|
+ form.daily_price_2h = prices.daily_price_2h;
|
|
|
|
|
+ }
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ if (provider) {
|
|
|
|
|
+ selectedUser.value = {
|
|
|
|
|
+ label: provider.user?.name || "",
|
|
|
|
|
+ value: provider.user?.id,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+</script>
|