ScheduleCancelDialog.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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-primary font16 fontbold">
  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-grey-8 font14 fontbold 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. :rules="[val => (val && val.trim().length >= 5) || ' ']"
  25. hide-bottom-space
  26. />
  27. </q-card-section>
  28. <q-card-section class="q-pt-xs q-pb-md q-px-lg">
  29. <div class="warning-box row no-wrap q-gutter-x-sm q-pa-sm">
  30. <q-icon name="mdi-alert-outline" color="secondary" size="22px" class="q-mt-xs flex-shrink-0" />
  31. <div class="font12 text-grey-8">
  32. <span>{{ $t('provider.dashboard.cancel_schedule.warning_before') }}</span>
  33. <span class="fontbold">{{ $t('provider.dashboard.cancel_schedule.warning_bold') }}</span>
  34. <span>{{ $t('provider.dashboard.cancel_schedule.warning_after') }}</span>
  35. </div>
  36. </div>
  37. </q-card-section>
  38. <q-card-section class="q-pt-none q-pb-lg q-px-lg">
  39. <div class="row justify-center q-gutter-x-md">
  40. <q-btn
  41. unelevated
  42. rounded
  43. no-caps
  44. size="sm"
  45. class="btn-action bg-grey-3 text-grey-8"
  46. :label="$t('provider.dashboard.cancel_schedule.btn_cancel')"
  47. @click="onDialogCancel"
  48. />
  49. <q-btn
  50. unelevated
  51. rounded
  52. no-caps
  53. color="secondary"
  54. class="btn-action"
  55. :loading="loading"
  56. size="sm"
  57. :disable="!cancelText || cancelText.trim().length < 5"
  58. :label="$t('provider.dashboard.cancel_schedule.btn_keep')"
  59. @click="confirmCancel"
  60. />
  61. </div>
  62. </q-card-section>
  63. </q-card>
  64. </q-dialog>
  65. </template>
  66. <script setup>
  67. import { ref } from 'vue'
  68. import { useDialogPluginComponent, useQuasar } from 'quasar'
  69. import { useI18n } from 'vue-i18n'
  70. import { cancelSchedule } from 'src/api/schedule'
  71. const props = defineProps({
  72. schedule: {
  73. type: Object,
  74. required: true
  75. }
  76. })
  77. const { t } = useI18n()
  78. const $q = useQuasar()
  79. const { dialogRef, onDialogHide, onDialogCancel, onDialogOK } = useDialogPluginComponent()
  80. const cancelText = ref('')
  81. const loading = ref(false)
  82. const confirmCancel = async () => {
  83. if (!cancelText.value || cancelText.value.trim().length < 5) return
  84. loading.value = true
  85. try {
  86. await cancelSchedule(props.schedule.id, cancelText.value.trim())
  87. onDialogOK()
  88. } catch {
  89. $q.notify({ message: t('http.errors.failed'), color: 'negative' })
  90. } finally {
  91. loading.value = false
  92. }
  93. }
  94. </script>
  95. <style scoped lang="scss">
  96. .cancel-dialog-card {
  97. width: 340px;
  98. max-width: 94vw;
  99. border-radius: 20px !important;
  100. overflow: hidden;
  101. }
  102. .cancel-title {
  103. line-height: 1.35;
  104. }
  105. .warning-box {
  106. background: #e8f4fd;
  107. border-radius: 10px;
  108. }
  109. .btn-action {
  110. min-width: 110px;
  111. }
  112. .flex-shrink-0 {
  113. flex-shrink: 0;
  114. }
  115. </style>