|
|
@@ -1,119 +1,270 @@
|
|
|
<template>
|
|
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
- <q-card class="q-dialog-plugin" style="width: 800px; max-width: 90vw">
|
|
|
+ <q-card class="q-dialog-plugin" 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">
|
|
|
- <ClientSelect
|
|
|
- v-model="selectedClient"
|
|
|
- :label="$t('schedules.client')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.client_id"
|
|
|
- :error-message="serverErrors?.client_id"
|
|
|
- :initial-id="schedule ? schedule.client_id : null"
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:model-value="onClientChange"
|
|
|
- />
|
|
|
+ <q-card-section class="row q-col-gutter-md">
|
|
|
+ <div class="col-12">
|
|
|
+ <div class="text-subtitle1 text-weight-bold q-mb-md">
|
|
|
+ {{ $t('schedules.schedule_info') }}
|
|
|
+ </div>
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <ClientSelect
|
|
|
+ v-model="selectedClient"
|
|
|
+ :label="$t('schedules.client')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.client_id"
|
|
|
+ :error-message="serverErrors?.client_id"
|
|
|
+ :initial-id="schedule ? schedule.client_id : null"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:model-value="onClientChange"
|
|
|
+ />
|
|
|
|
|
|
- <ProviderSelect
|
|
|
- v-model="selectedProvider"
|
|
|
- :label="$t('schedules.provider')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.provider_id"
|
|
|
- :error-message="serverErrors?.provider_id"
|
|
|
- :initial-id="schedule ? schedule.provider_id : null"
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:model-value="onProviderChange"
|
|
|
- />
|
|
|
+ <ProviderSelect
|
|
|
+ v-model="selectedProvider"
|
|
|
+ :label="$t('schedules.provider')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.provider_id"
|
|
|
+ :error-message="serverErrors?.provider_id"
|
|
|
+ :initial-id="schedule ? schedule.provider_id : null"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:model-value="onProviderChange"
|
|
|
+ />
|
|
|
|
|
|
- <AddressSelect
|
|
|
- v-model="selectedAddress"
|
|
|
- :label="$t('schedules.address')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.address_id"
|
|
|
- :error-message="serverErrors?.address_id"
|
|
|
- :initial-id="schedule ? schedule.address_id : null"
|
|
|
- :client-id="form.client_id"
|
|
|
- :disabled="!form.client_id"
|
|
|
- class="col-12"
|
|
|
- @update:model-value="serverErrors.address_id = null"
|
|
|
- />
|
|
|
+ <AddressSelect
|
|
|
+ v-model="selectedAddress"
|
|
|
+ :label="$t('schedules.address')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.address_id"
|
|
|
+ :error-message="serverErrors?.address_id"
|
|
|
+ :initial-id="schedule ? schedule.address_id : null"
|
|
|
+ :client-id="form.client_id"
|
|
|
+ :disabled="!form.client_id"
|
|
|
+ class="col-12"
|
|
|
+ @update:model-value="serverErrors.address_id = null"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <DefaultInputDatePicker
|
|
|
- v-model:untreated-date="form.date"
|
|
|
- :label="$t('schedules.date')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.date"
|
|
|
- :error-message="serverErrors?.date"
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:untreated-date="serverErrors.date = null"
|
|
|
- />
|
|
|
+ <template v-if="schedule">
|
|
|
+ <q-separator class="col-12" />
|
|
|
+
|
|
|
+ <div class="col-12">
|
|
|
+ <div class="text-subtitle1 text-weight-bold q-mb-md">
|
|
|
+ {{ $t('schedules.schedule_details') }}
|
|
|
+ </div>
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <DefaultInputDatePicker
|
|
|
+ v-model:untreated-date="form.date"
|
|
|
+ :label="$t('schedules.date')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.date"
|
|
|
+ :error-message="serverErrors?.date"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:untreated-date="serverErrors.date = null"
|
|
|
+ />
|
|
|
|
|
|
- <q-select
|
|
|
- v-model="form.period_type"
|
|
|
- :label="$t('schedules.period_type')"
|
|
|
- :options="periodOptions"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.period_type"
|
|
|
- :error-message="serverErrors?.period_type"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:model-value="onPeriodChange"
|
|
|
- />
|
|
|
+ <q-select
|
|
|
+ v-model="form.period_type"
|
|
|
+ :label="$t('schedules.period_type')"
|
|
|
+ :options="periodOptions"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.period_type"
|
|
|
+ :error-message="serverErrors?.period_type"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:model-value="onPeriodChange"
|
|
|
+ />
|
|
|
|
|
|
- <DefaultInputTimePicker
|
|
|
- v-model:untreated-time="form.start_time"
|
|
|
- :label="$t('schedules.start_time')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.start_time"
|
|
|
- :error-message="serverErrors?.start_time"
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:untreated-time="onStartTimeChange"
|
|
|
- />
|
|
|
+ <DefaultInputTimePicker
|
|
|
+ v-model:untreated-time="form.start_time"
|
|
|
+ :label="$t('schedules.start_time')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.start_time"
|
|
|
+ :error-message="serverErrors?.start_time"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:untreated-time="onStartTimeChange"
|
|
|
+ />
|
|
|
|
|
|
- <DefaultInputTimePicker
|
|
|
- v-model:untreated-time="form.end_time"
|
|
|
- :label="$t('schedules.end_time')"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.end_time"
|
|
|
- :error-message="serverErrors?.end_time"
|
|
|
- :disabled="true"
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:untreated-time="serverErrors.end_time = null"
|
|
|
- />
|
|
|
+ <DefaultInputTimePicker
|
|
|
+ v-model:untreated-time="form.end_time"
|
|
|
+ :label="$t('schedules.end_time')"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.end_time"
|
|
|
+ :error-message="serverErrors?.end_time"
|
|
|
+ :disabled="true"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:untreated-time="serverErrors.end_time = null"
|
|
|
+ />
|
|
|
|
|
|
- <q-select
|
|
|
- v-model="form.status"
|
|
|
- :label="$t('schedules.status')"
|
|
|
- :options="statusOptions"
|
|
|
- :rules="[inputRules.required]"
|
|
|
- :error="!!serverErrors?.status"
|
|
|
- :error-message="serverErrors?.status"
|
|
|
- :disable="!schedule"
|
|
|
- emit-value
|
|
|
- map-options
|
|
|
- class="col-12 col-md-6"
|
|
|
- @update:model-value="serverErrors.status = null"
|
|
|
- />
|
|
|
+ <q-input
|
|
|
+ v-model="form.total_amount"
|
|
|
+ :label="$t('schedules.total_amount')"
|
|
|
+ :prefix="'R$'"
|
|
|
+ :readonly="true"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ />
|
|
|
|
|
|
- <q-input
|
|
|
- v-model="form.total_amount"
|
|
|
- :label="$t('schedules.total_amount')"
|
|
|
- :prefix="'R$'"
|
|
|
- :readonly="true"
|
|
|
- class="col-12 col-md-6"
|
|
|
- />
|
|
|
+ <q-select
|
|
|
+ v-model="form.status"
|
|
|
+ :label="$t('schedules.status')"
|
|
|
+ :options="statusOptions"
|
|
|
+ :rules="[inputRules.required]"
|
|
|
+ :error="!!serverErrors?.status"
|
|
|
+ :error-message="serverErrors?.status"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:model-value="serverErrors.status = null"
|
|
|
+ />
|
|
|
|
|
|
- <q-checkbox
|
|
|
- v-if="schedule"
|
|
|
- v-model="form.code_verified"
|
|
|
- :label="$t('schedules.code_verified')"
|
|
|
- class="col-12"
|
|
|
- />
|
|
|
+ <q-checkbox
|
|
|
+ v-model="form.code_verified"
|
|
|
+ :label="$t('schedules.code_verified')"
|
|
|
+ class="col-12"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else>
|
|
|
+ <q-separator class="col-12" />
|
|
|
+
|
|
|
+ <div class="col-12">
|
|
|
+ <div class="text-subtitle1 text-weight-bold q-mb-md">
|
|
|
+ {{ $t('schedules.schedule_dates') }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="!showDateForm" class="row justify-center q-py-lg">
|
|
|
+ <q-btn
|
|
|
+ icon="add"
|
|
|
+ :label="$t('schedules.add_date')"
|
|
|
+ color="primary"
|
|
|
+ size="md"
|
|
|
+ unelevated
|
|
|
+ @click="showAddDateForm"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-slide-transition>
|
|
|
+ <div v-if="showDateForm">
|
|
|
+ <q-card flat bordered class="q-mb-md">
|
|
|
+ <q-card-section>
|
|
|
+ <div class="row q-col-gutter-sm">
|
|
|
+ <DefaultInputDatePicker
|
|
|
+ v-model:untreated-date="form.date"
|
|
|
+ :label="$t('schedules.date')"
|
|
|
+ :error="!!serverErrors?.date"
|
|
|
+ :error-message="serverErrors?.date"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:untreated-date="serverErrors.date = null"
|
|
|
+ />
|
|
|
+
|
|
|
+ <q-select
|
|
|
+ v-model="form.period_type"
|
|
|
+ :label="$t('schedules.period_type')"
|
|
|
+ :options="periodOptions"
|
|
|
+ :error="!!serverErrors?.period_type"
|
|
|
+ :error-message="serverErrors?.period_type"
|
|
|
+ emit-value
|
|
|
+ map-options
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:model-value="onPeriodChange"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultInputTimePicker
|
|
|
+ v-model:untreated-time="form.start_time"
|
|
|
+ :label="$t('schedules.start_time')"
|
|
|
+ :error="!!serverErrors?.start_time"
|
|
|
+ :error-message="serverErrors?.start_time"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ @update:untreated-time="onStartTimeChange"
|
|
|
+ />
|
|
|
+
|
|
|
+ <DefaultInputTimePicker
|
|
|
+ v-model:untreated-time="form.end_time"
|
|
|
+ :label="$t('schedules.end_time')"
|
|
|
+ :disabled="true"
|
|
|
+ class="col-12 col-md-6"
|
|
|
+ />
|
|
|
+
|
|
|
+ <q-input
|
|
|
+ v-model="form.total_amount"
|
|
|
+ :label="$t('schedules.total_amount')"
|
|
|
+ :prefix="'R$'"
|
|
|
+ :readonly="true"
|
|
|
+ class="col-12"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-actions align="right">
|
|
|
+ <q-btn
|
|
|
+ v-if="editingDateIndex !== null"
|
|
|
+ flat
|
|
|
+ icon="close"
|
|
|
+ :label="$t('common.actions.cancel')"
|
|
|
+ color="negative"
|
|
|
+ @click="cancelDateEdit"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ :icon="editingDateIndex === null ? 'save' : 'check'"
|
|
|
+ :label="editingDateIndex === null ? $t('common.actions.save') : $t('common.actions.update')"
|
|
|
+ :color="editingDateIndex === null ? 'primary' : 'positive'"
|
|
|
+ unelevated
|
|
|
+ @click="addOrUpdateDate"
|
|
|
+ />
|
|
|
+ </q-card-actions>
|
|
|
+ </q-card>
|
|
|
+ </div>
|
|
|
+ </q-slide-transition>
|
|
|
+
|
|
|
+ <q-slide-transition>
|
|
|
+ <div v-if="scheduleDates?.length > 0">
|
|
|
+ <q-table
|
|
|
+ :rows="scheduleDates"
|
|
|
+ :columns="dateColumns"
|
|
|
+ row-key="date"
|
|
|
+ :rows-per-page-options="[0]"
|
|
|
+ flat
|
|
|
+ bordered
|
|
|
+ class="q-mt-md"
|
|
|
+ >
|
|
|
+ <template #body-cell-actions="slotProps">
|
|
|
+ <q-td :props="slotProps">
|
|
|
+ <q-btn
|
|
|
+ flat
|
|
|
+ dense
|
|
|
+ round
|
|
|
+ icon="edit"
|
|
|
+ color="primary"
|
|
|
+ size="sm"
|
|
|
+ @click="editDate(slotProps.rowIndex)"
|
|
|
+ >
|
|
|
+ <q-tooltip>{{ $t('common.actions.edit') }}</q-tooltip>
|
|
|
+ </q-btn>
|
|
|
+ <q-btn
|
|
|
+ flat
|
|
|
+ dense
|
|
|
+ round
|
|
|
+ icon="delete"
|
|
|
+ color="negative"
|
|
|
+ size="sm"
|
|
|
+ @click="removeScheduleDate(slotProps.rowIndex)"
|
|
|
+ >
|
|
|
+ <q-tooltip>{{ $t('common.actions.delete') }}</q-tooltip>
|
|
|
+ </q-btn>
|
|
|
+ </q-td>
|
|
|
+ </template>
|
|
|
+ </q-table>
|
|
|
+ </div>
|
|
|
+ </q-slide-transition>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</q-card-section>
|
|
|
|
|
|
- <q-card-actions align="right">
|
|
|
+ <q-card-actions align="right" class="q-px-md q-pb-md">
|
|
|
<q-btn
|
|
|
flat
|
|
|
:label="$t('common.actions.cancel')"
|
|
|
@@ -124,8 +275,9 @@
|
|
|
type="submit"
|
|
|
:label="$t('common.actions.save')"
|
|
|
:loading="loading"
|
|
|
- :disable="!hasUpdatedFields"
|
|
|
+ :disable="isSaveDisabled"
|
|
|
color="primary"
|
|
|
+ unelevated
|
|
|
/>
|
|
|
</q-card-actions>
|
|
|
</q-form>
|
|
|
@@ -134,20 +286,20 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed, onMounted } from 'vue'
|
|
|
-import { useDialogPluginComponent } from 'quasar'
|
|
|
-import { useFormUpdateTracker } from 'src/composables/useFormUpdateTracker'
|
|
|
-import { useSubmitHandler } from 'src/composables/useSubmitHandler'
|
|
|
-import { createSchedule, updateSchedule } from 'src/api/schedule'
|
|
|
-import { getProvider } from 'src/api/provider'
|
|
|
-import DefaultDialogHeader from 'src/components/defaults/DefaultDialogHeader.vue'
|
|
|
-import ClientSelect from 'src/components/client/ClientSelect.vue'
|
|
|
-import ProviderSelect from 'src/components/provider/ProviderSelect.vue'
|
|
|
-import AddressSelect from 'src/components/address/AddressSelect.vue'
|
|
|
-import DefaultInputDatePicker from 'src/components/defaults/DefaultInputDatePicker.vue'
|
|
|
-import DefaultInputTimePicker from 'src/components/defaults/DefaultInputTimePicker.vue'
|
|
|
-import { useInputRules } from 'src/composables/useInputRules'
|
|
|
-import { useI18n } from 'vue-i18n'
|
|
|
+import { ref, computed, onMounted } from 'vue';
|
|
|
+import { useDialogPluginComponent } from 'quasar';
|
|
|
+import { useFormUpdateTracker } from 'src/composables/useFormUpdateTracker';
|
|
|
+import { useSubmitHandler } from 'src/composables/useSubmitHandler';
|
|
|
+import { createSchedule, updateSchedule } from 'src/api/schedule';
|
|
|
+import { getProvider } from 'src/api/provider';
|
|
|
+import DefaultDialogHeader from 'src/components/defaults/DefaultDialogHeader.vue';
|
|
|
+import ClientSelect from 'src/components/client/ClientSelect.vue';
|
|
|
+import ProviderSelect from 'src/components/provider/ProviderSelect.vue';
|
|
|
+import AddressSelect from 'src/components/address/AddressSelect.vue';
|
|
|
+import DefaultInputDatePicker from 'src/components/defaults/DefaultInputDatePicker.vue';
|
|
|
+import DefaultInputTimePicker from 'src/components/defaults/DefaultInputTimePicker.vue';
|
|
|
+import { useInputRules } from 'src/composables/useInputRules';
|
|
|
+import { useI18n } from 'vue-i18n';
|
|
|
|
|
|
const props = defineProps({
|
|
|
schedule: {
|
|
|
@@ -158,31 +310,37 @@ const props = defineProps({
|
|
|
type: Function,
|
|
|
default: () => ''
|
|
|
}
|
|
|
-})
|
|
|
+});
|
|
|
+
|
|
|
+defineEmits([...useDialogPluginComponent.emits]);
|
|
|
+const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent();
|
|
|
+const { inputRules } = useInputRules();
|
|
|
+const { t } = useI18n();
|
|
|
+const formRef = ref(null);
|
|
|
|
|
|
-defineEmits([...useDialogPluginComponent.emits])
|
|
|
-const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
|
|
|
-const { inputRules } = useInputRules()
|
|
|
-const { t } = useI18n()
|
|
|
-const formRef = ref(null)
|
|
|
-const selectedClient = ref(null)
|
|
|
-const selectedProvider = ref(null)
|
|
|
-const selectedAddress = ref(null)
|
|
|
-const providerData = ref(null)
|
|
|
+// Estados
|
|
|
+const selectedClient = ref(null);
|
|
|
+const selectedProvider = ref(null);
|
|
|
+const selectedAddress = ref(null);
|
|
|
+const providerData = ref(null);
|
|
|
+
|
|
|
+const scheduleDates = ref([]);
|
|
|
+const editingDateIndex = ref(null);
|
|
|
+const showDateForm = ref(false);
|
|
|
|
|
|
const { form, getUpdatedFields, hasUpdatedFields } = useFormUpdateTracker({
|
|
|
client_id: props.schedule ? props.schedule.client_id : null,
|
|
|
provider_id: props.schedule ? props.schedule.provider_id : null,
|
|
|
address_id: props.schedule ? props.schedule.address_id : null,
|
|
|
date: props.schedule ? props.schedule.date : null,
|
|
|
- period_type: props.schedule ? props.schedule.period_type : '8',
|
|
|
+ period_type: props.schedule ? props.schedule.period_type : null,
|
|
|
schedule_type: props.schedule ? props.schedule.schedule_type : 'default',
|
|
|
start_time: props.schedule ? props.schedule.start_time : null,
|
|
|
end_time: props.schedule ? props.schedule.end_time : null,
|
|
|
status: props.schedule ? props.schedule.status : 'pending',
|
|
|
total_amount: props.schedule ? props.schedule.total_amount : 0,
|
|
|
code_verified: props.schedule ? props.schedule.code_verified : false
|
|
|
-})
|
|
|
+});
|
|
|
|
|
|
const {
|
|
|
loading,
|
|
|
@@ -191,14 +349,14 @@ const {
|
|
|
} = useSubmitHandler({
|
|
|
onSuccess: () => onDialogOK(true),
|
|
|
formRef: formRef,
|
|
|
-})
|
|
|
+});
|
|
|
|
|
|
const periodOptions = computed(() => [
|
|
|
{ label: t('schedules.period_types.2'), value: '2' },
|
|
|
{ label: t('schedules.period_types.4'), value: '4' },
|
|
|
{ label: t('schedules.period_types.6'), value: '6' },
|
|
|
{ label: t('schedules.period_types.8'), value: '8' }
|
|
|
-])
|
|
|
+]);
|
|
|
|
|
|
const statusOptions = computed(() => [
|
|
|
{ label: t('schedules.statuses.pending'), value: 'pending' },
|
|
|
@@ -208,89 +366,216 @@ const statusOptions = computed(() => [
|
|
|
{ label: t('schedules.statuses.cancelled'), value: 'cancelled' },
|
|
|
{ label: t('schedules.statuses.started'), value: 'started' },
|
|
|
{ label: t('schedules.statuses.finished'), value: 'finished' }
|
|
|
-])
|
|
|
+]);
|
|
|
+
|
|
|
+const dateColumns = computed(() => [
|
|
|
+ { name: 'date', label: t('schedules.date'), field: 'date', align: 'left', format: formatDate },
|
|
|
+ { name: 'period_type', label: t('schedules.period'), field: 'period_type', align: 'center', format: (val) => `${val}h` },
|
|
|
+ { name: 'start_time', label: t('schedules.start_time'), field: 'start_time', align: 'center', format: (val) => val?.substring(0, 5) },
|
|
|
+ { name: 'end_time', label: t('schedules.end_time'), field: 'end_time', align: 'center', format: (val) => val?.substring(0, 5) },
|
|
|
+ { name: 'total_amount', label: t('schedules.total_amount'), field: 'total_amount', align: 'right', format: (val) => `R$ ${Number(val).toFixed(2)}` },
|
|
|
+ { name: 'actions', label: t('common.actions.title'), field: 'actions', align: 'center' }
|
|
|
+]);
|
|
|
+
|
|
|
+const isSaveDisabled = computed(() => {
|
|
|
+ if (props.schedule) {
|
|
|
+ return !hasUpdatedFields.value;
|
|
|
+ }
|
|
|
+ return scheduleDates.value.length === 0;
|
|
|
+})
|
|
|
+
|
|
|
+const formatDate = (date) => {
|
|
|
+ if (!date) return '';
|
|
|
+ const [year, month, day] = date.split('-');
|
|
|
+ return `${day}/${month}/${year}`;
|
|
|
+}
|
|
|
|
|
|
const onClientChange = (client) => {
|
|
|
- form.client_id = client?.value || null
|
|
|
+ form.client_id = client?.value || null;
|
|
|
if (!props.schedule) {
|
|
|
- selectedAddress.value = null
|
|
|
- form.address_id = null
|
|
|
+ selectedAddress.value = null;
|
|
|
+ form.address_id = null;
|
|
|
}
|
|
|
- serverErrors.client_id = null
|
|
|
+ serverErrors.client_id = null;
|
|
|
}
|
|
|
|
|
|
const onProviderChange = async (provider) => {
|
|
|
- form.provider_id = provider?.value || null
|
|
|
- serverErrors.provider_id = null
|
|
|
+ form.provider_id = provider?.value || null;
|
|
|
+ serverErrors.provider_id = null;
|
|
|
|
|
|
if (form.provider_id) {
|
|
|
try {
|
|
|
- providerData.value = await getProvider(form.provider_id)
|
|
|
- calculateTotalAmount()
|
|
|
+ providerData.value = await getProvider(form.provider_id);
|
|
|
+ if (props.schedule) {
|
|
|
+ calculateTotalAmount();
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
- console.error('Error loading provider:', error)
|
|
|
+ console.error('Error loading provider:', error);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const onPeriodChange = () => {
|
|
|
- serverErrors.period_type = null
|
|
|
- calculateEndTime()
|
|
|
- calculateTotalAmount()
|
|
|
+ serverErrors.period_type = null;
|
|
|
+ calculateEndTime();
|
|
|
+ calculateTotalAmount();
|
|
|
}
|
|
|
|
|
|
const onStartTimeChange = () => {
|
|
|
- serverErrors.start_time = null
|
|
|
- calculateEndTime()
|
|
|
+ serverErrors.start_time = null;
|
|
|
+ calculateEndTime();
|
|
|
}
|
|
|
|
|
|
const calculateEndTime = () => {
|
|
|
- if (!form.start_time || !form.period_type) return
|
|
|
+ if (!form.start_time || !form.period_type) return;
|
|
|
|
|
|
- const [hours, minutes] = form.start_time.split(':').map(Number)
|
|
|
- const periodHours = parseInt(form.period_type)
|
|
|
+ const [hours, minutes] = form.start_time.split(':').map(Number);
|
|
|
+ const periodHours = parseInt(form.period_type);
|
|
|
|
|
|
- const endHours = hours + periodHours
|
|
|
- const endMinutes = minutes
|
|
|
+ const endHours = hours + periodHours;
|
|
|
+ const endMinutes = minutes;
|
|
|
|
|
|
- form.end_time = `${String(endHours).padStart(2, '0')}:${String(endMinutes).padStart(2, '0')}:00`
|
|
|
+ form.end_time = `${String(endHours).padStart(2, '0')}:${String(endMinutes).padStart(2, '0')}`;
|
|
|
}
|
|
|
|
|
|
const calculateTotalAmount = () => {
|
|
|
- if (!providerData.value || !form.period_type) return
|
|
|
+ if (!providerData.value || !form.period_type) return;
|
|
|
const rateMap = {
|
|
|
'2': providerData.value.daily_price_2h,
|
|
|
'4': providerData.value.daily_price_4h,
|
|
|
'6': providerData.value.daily_price_6h,
|
|
|
'8': providerData.value.daily_price_8h
|
|
|
+ };
|
|
|
+ form.total_amount = rateMap[form.period_type] || 0;
|
|
|
+}
|
|
|
+
|
|
|
+const showAddDateForm = () => {
|
|
|
+ showDateForm.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+const validateAddDate = () => {
|
|
|
+ let isValid = true;
|
|
|
+
|
|
|
+ if (!form.date) {
|
|
|
+ serverErrors.date = t('common.validations.required');
|
|
|
+ isValid = false;
|
|
|
+ } else {
|
|
|
+ const isDuplicate = scheduleDates.value.some((item, index) =>
|
|
|
+ item.date === form.date && index !== editingDateIndex.value
|
|
|
+ );
|
|
|
+ if (isDuplicate) {
|
|
|
+ serverErrors.date = t('schedules.date_already_added');
|
|
|
+ isValid = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!form.period_type) {
|
|
|
+ serverErrors.period_type = t('common.validations.required');
|
|
|
+ isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!form.start_time) {
|
|
|
+ serverErrors.start_time = t('common.validations.required');
|
|
|
+ isValid = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return isValid;
|
|
|
+}
|
|
|
+
|
|
|
+const addOrUpdateDate = () => {
|
|
|
+ if (!validateAddDate()) return;
|
|
|
+
|
|
|
+ const dateData = {
|
|
|
+ date: form.date,
|
|
|
+ period_type: form.period_type,
|
|
|
+ start_time: form.start_time,
|
|
|
+ end_time: form.end_time,
|
|
|
+ total_amount: form.total_amount
|
|
|
+ };
|
|
|
+
|
|
|
+ if (editingDateIndex.value !== null) {
|
|
|
+ scheduleDates.value[editingDateIndex.value] = dateData;
|
|
|
+ editingDateIndex.value = null
|
|
|
+ } else {
|
|
|
+ scheduleDates.value.push(dateData);
|
|
|
}
|
|
|
- form.total_amount = rateMap[form.period_type] || 0
|
|
|
+
|
|
|
+ resetDateForm()
|
|
|
+ showDateForm.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+const editDate = (index) => {
|
|
|
+ const item = scheduleDates.value[index];
|
|
|
+ form.date = item.date;
|
|
|
+ form.period_type = item.period_type;
|
|
|
+ form.start_time = item.start_time;
|
|
|
+ form.end_time = item.end_time;
|
|
|
+ form.total_amount = item.total_amount;
|
|
|
+ editingDateIndex.value = index;
|
|
|
+ showDateForm.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+const removeScheduleDate = (index) => {
|
|
|
+ scheduleDates.value.splice(index, 1);
|
|
|
+ if (editingDateIndex.value === index) {
|
|
|
+ cancelDateEdit();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const cancelDateEdit = () => {
|
|
|
+ editingDateIndex.value = null;
|
|
|
+ resetDateForm();
|
|
|
+ showDateForm.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+const resetDateForm = () => {
|
|
|
+ form.date = null;
|
|
|
+ form.period_type = null;
|
|
|
+ form.start_time = null;
|
|
|
+ form.end_time = null;
|
|
|
+ form.total_amount = 0;
|
|
|
+ serverErrors.date = null;
|
|
|
+ serverErrors.period_type = null;
|
|
|
+ serverErrors.start_time = null;
|
|
|
}
|
|
|
|
|
|
const onOKClick = async () => {
|
|
|
if (selectedClient.value?.value) {
|
|
|
- form.client_id = selectedClient.value.value
|
|
|
+ form.client_id = selectedClient.value.value;
|
|
|
}
|
|
|
if (selectedProvider.value?.value) {
|
|
|
- form.provider_id = selectedProvider.value.value
|
|
|
+ form.provider_id = selectedProvider.value.value;
|
|
|
}
|
|
|
if (selectedAddress.value?.value) {
|
|
|
- form.address_id = selectedAddress.value.value
|
|
|
+ form.address_id = selectedAddress.value.value;
|
|
|
}
|
|
|
|
|
|
if (props.schedule) {
|
|
|
- await submitForm(() => updateSchedule(props.schedule.id, getUpdatedFields.value))
|
|
|
+ await submitForm(() => updateSchedule(props.schedule.id, getUpdatedFields.value));
|
|
|
} else {
|
|
|
- await submitForm(() => createSchedule({ ...form }))
|
|
|
+ if (scheduleDates.value.length === 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const formData = {
|
|
|
+ client_id: form.client_id,
|
|
|
+ provider_id: form.provider_id,
|
|
|
+ address_id: form.address_id,
|
|
|
+ schedule_type: form.schedule_type,
|
|
|
+ status: form.status,
|
|
|
+ schedules: scheduleDates.value
|
|
|
+ };
|
|
|
+
|
|
|
+ await submitForm(() => createSchedule(formData));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
onMounted(async () => {
|
|
|
if (props.schedule?.provider_id) {
|
|
|
try {
|
|
|
- providerData.value = await getProvider(props.schedule.provider_id)
|
|
|
+ providerData.value = await getProvider(props.schedule.provider_id);
|
|
|
} catch (error) {
|
|
|
- console.error('Error loading provider:', error)
|
|
|
+ console.error('Error loading provider:', error);
|
|
|
}
|
|
|
}
|
|
|
})
|