|
|
@@ -0,0 +1,138 @@
|
|
|
+<template>
|
|
|
+ <q-dialog ref="dialogRef" @hide="onDialogHide">
|
|
|
+ <q-card class="cancel-dialog-card bg-surface shadow-card" :flat="false">
|
|
|
+
|
|
|
+ <div class="row justify-end q-pt-sm q-pr-sm">
|
|
|
+ <q-btn flat round dense icon="close" color="grey-6" size="sm" @click="onDialogCancel" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-none q-pb-sm q-px-lg text-center">
|
|
|
+ <div class="cancel-title text-secondary text-weight-bold">
|
|
|
+ {{ $t('provider.dashboard.cancel_schedule.title') }} {{ schedule.id }}
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-none q-pb-sm q-px-lg">
|
|
|
+ <div class="text-body2 text-grey-8 text-weight-bold q-mb-xs">
|
|
|
+ {{ $t('provider.dashboard.cancel_schedule.reason_label') }}
|
|
|
+ </div>
|
|
|
+ <q-input
|
|
|
+ v-model="cancelText"
|
|
|
+ type="textarea"
|
|
|
+ outlined
|
|
|
+ dense
|
|
|
+ :placeholder="$t('provider.dashboard.cancel_schedule.reason_placeholder')"
|
|
|
+ rows="4"
|
|
|
+ color="secondary"
|
|
|
+ :rules="[val => (val && val.trim().length >= 5) || ' ']"
|
|
|
+ hide-bottom-space
|
|
|
+ />
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-xs q-pb-md q-px-lg">
|
|
|
+ <div class="warning-box row no-wrap q-gutter-x-sm q-pa-sm">
|
|
|
+ <q-icon name="mdi-alert-outline" color="secondary" size="22px" class="q-mt-xs flex-shrink-0" />
|
|
|
+ <div>
|
|
|
+ <span class="text-caption text-weight-bold text-grey-9">
|
|
|
+ {{ $t('provider.dashboard.cancel_schedule.warning_title') }}
|
|
|
+ </span>
|
|
|
+ <span class="text-caption text-grey-8">
|
|
|
+ {{ ' ' + $t('provider.dashboard.cancel_schedule.warning_free') }}
|
|
|
+ </span>
|
|
|
+ <br />
|
|
|
+ <span class="text-caption text-grey-8">
|
|
|
+ {{ $t('provider.dashboard.cancel_schedule.warning_fee') }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ <q-card-section class="q-pt-none q-pb-lg q-px-lg">
|
|
|
+ <div class="row justify-center q-gutter-x-md">
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ class="btn-action bg-grey-3 text-grey-8"
|
|
|
+ :label="$t('provider.dashboard.cancel_schedule.btn_cancel')"
|
|
|
+ @click="onDialogCancel"
|
|
|
+ />
|
|
|
+ <q-btn
|
|
|
+ unelevated
|
|
|
+ rounded
|
|
|
+ no-caps
|
|
|
+ color="secondary"
|
|
|
+ class="btn-action"
|
|
|
+ :loading="loading"
|
|
|
+ :disable="!cancelText || cancelText.trim().length < 5"
|
|
|
+ :label="$t('provider.dashboard.cancel_schedule.btn_keep')"
|
|
|
+ @click="confirmCancel"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </q-card-section>
|
|
|
+
|
|
|
+ </q-card>
|
|
|
+ </q-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref } from 'vue'
|
|
|
+import { useDialogPluginComponent, useQuasar } from 'quasar'
|
|
|
+import { useI18n } from 'vue-i18n'
|
|
|
+import { cancelSchedule } from 'src/api/schedule'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ schedule: {
|
|
|
+ type: Object,
|
|
|
+ required: true
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+const $q = useQuasar()
|
|
|
+const { dialogRef, onDialogHide, onDialogCancel } = useDialogPluginComponent()
|
|
|
+
|
|
|
+const cancelText = ref('')
|
|
|
+const loading = ref(false)
|
|
|
+
|
|
|
+const confirmCancel = async () => {
|
|
|
+ if (!cancelText.value || cancelText.value.trim().length < 5) return
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ await cancelSchedule(props.schedule.id, cancelText.value.trim())
|
|
|
+ dialogRef.value.hide()
|
|
|
+ } catch {
|
|
|
+ $q.notify({ message: t('http.errors.failed'), color: 'negative' })
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.cancel-dialog-card {
|
|
|
+ width: 340px;
|
|
|
+ max-width: 94vw;
|
|
|
+ border-radius: 20px !important;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.cancel-title {
|
|
|
+ font-size: 18px;
|
|
|
+ line-height: 1.35;
|
|
|
+}
|
|
|
+
|
|
|
+.warning-box {
|
|
|
+ background: #e8f4fd;
|
|
|
+ border-radius: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.btn-action {
|
|
|
+ min-width: 110px;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+
|
|
|
+.flex-shrink-0 {
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+</style>
|