ScheduleCancelDialog.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <template>
  2. <q-dialog ref="dialogRef" @hide="onDialogHide">
  3. <q-card class="cancel-dialog-card bg-surface shadow-card" :flat="false">
  4. <div class="row justify-end q-pt-sm q-pr-sm">
  5. <q-btn flat round dense icon="close" color="grey-6" size="sm" @click="onDialogCancel" />
  6. </div>
  7. <q-card-section class="q-pt-none q-pb-sm q-px-lg text-center">
  8. <div class="cancel-title text-secondary text-weight-bold">
  9. {{ $t('provider.dashboard.cancel_schedule.title') }}
  10. </div>
  11. </q-card-section>
  12. <q-card-section class="q-pt-none q-pb-sm q-px-lg">
  13. <div class="text-body2 text-grey-8 text-weight-bold q-mb-xs">
  14. {{ $t('provider.dashboard.cancel_schedule.reason_label') }}
  15. </div>
  16. <q-input
  17. v-model="cancelText"
  18. type="textarea"
  19. outlined
  20. dense
  21. :placeholder="$t('provider.dashboard.cancel_schedule.reason_placeholder')"
  22. rows="4"
  23. color="secondary"
  24. input-class="text-black"
  25. :rules="[val => (val && val.trim().length >= 5) || ' ']"
  26. hide-bottom-space
  27. />
  28. </q-card-section>
  29. <q-card-section class="q-pt-xs q-pb-md q-px-lg">
  30. <div class="warning-box row no-wrap q-gutter-x-sm q-pa-sm">
  31. <q-icon name="mdi-alert-outline" color="secondary" size="22px" class="q-mt-xs flex-shrink-0" />
  32. <div>
  33. <span class="text-caption text-weight-bold text-grey-9">
  34. {{ $t('provider.dashboard.cancel_schedule.warning_title') }}
  35. </span>
  36. <span class="text-caption text-grey-8">
  37. {{ ' ' + $t('provider.dashboard.cancel_schedule.warning_free') }}
  38. </span>
  39. <br />
  40. <span class="text-caption text-grey-8">
  41. {{ $t('provider.dashboard.cancel_schedule.warning_fee') }}
  42. </span>
  43. </div>
  44. </div>
  45. </q-card-section>
  46. <q-card-section class="q-pt-none q-pb-lg q-px-lg">
  47. <div class="row justify-center q-gutter-x-md">
  48. <q-btn
  49. unelevated
  50. rounded
  51. no-caps
  52. class="btn-action bg-grey-3 text-grey-8"
  53. :label="$t('provider.dashboard.cancel_schedule.btn_back')"
  54. @click="onDialogCancel"
  55. />
  56. <q-btn
  57. unelevated
  58. rounded
  59. no-caps
  60. color="secondary"
  61. class="btn-action"
  62. :loading="loading"
  63. :disable="!cancelText || cancelText.trim().length < 5"
  64. :label="$t('provider.dashboard.cancel_schedule.btn_keep')"
  65. @click="confirmCancel"
  66. />
  67. </div>
  68. </q-card-section>
  69. </q-card>
  70. </q-dialog>
  71. </template>
  72. <script setup>
  73. import { ref } from 'vue'
  74. import { useDialogPluginComponent, useQuasar } from 'quasar'
  75. import { useI18n } from 'vue-i18n'
  76. import { cancelSchedule } from 'src/api/schedule'
  77. const props = defineProps({
  78. schedule: {
  79. type: Object,
  80. required: true
  81. }
  82. })
  83. const { t } = useI18n()
  84. const $q = useQuasar()
  85. const { dialogRef, onDialogHide, onDialogCancel } = useDialogPluginComponent()
  86. const cancelText = ref('')
  87. const loading = ref(false)
  88. const confirmCancel = async () => {
  89. if (!cancelText.value || cancelText.value.trim().length < 5) return
  90. loading.value = true
  91. try {
  92. await cancelSchedule(props.schedule.id, cancelText.value.trim())
  93. dialogRef.value.hide()
  94. } catch {
  95. $q.notify({ message: t('http.errors.failed'), color: 'negative' })
  96. } finally {
  97. loading.value = false
  98. }
  99. }
  100. </script>
  101. <style scoped lang="scss">
  102. .cancel-dialog-card {
  103. width: 340px;
  104. max-width: 94vw;
  105. border-radius: 20px !important;
  106. overflow: hidden;
  107. }
  108. .cancel-title {
  109. font-size: 18px;
  110. line-height: 1.35;
  111. }
  112. .warning-box {
  113. background: #e8f4fd;
  114. border-radius: 10px;
  115. }
  116. .btn-action {
  117. min-width: 110px;
  118. font-weight: 700;
  119. }
  120. .flex-shrink-0 {
  121. flex-shrink: 0;
  122. }
  123. </style>