Form.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <template>
  2. <main>
  3. <v-form
  4. ref="form"
  5. v-model="properties.valid"
  6. lazy-validation
  7. :readonly="readOnly"
  8. >
  9. <v-container fluid class="container btnActions">
  10. <v-row>
  11. <v-col cols="12" sm="12">
  12. <slot name="form.button" />
  13. <v-btn v-if="!readOnly" class="mr-4 ot_green ot_white--text" @click="submit">
  14. {{ $t('save') }}
  15. </v-btn>
  16. </v-col>
  17. </v-row>
  18. </v-container>
  19. <slot name="form.input" v-bind="{entry,updateRepository}" />
  20. <v-container fluid class="container btnActions">
  21. <v-row>
  22. <v-col cols="12" sm="12">
  23. <slot name="form.button" />
  24. <v-btn v-if="!readOnly" class="mr-4 ot_green ot_white--text" @click="submit">
  25. {{ $t('save') }}
  26. </v-btn>
  27. </v-col>
  28. </v-row>
  29. </v-container>
  30. </v-form>
  31. <lazy-LayoutDialog
  32. :show="showDialog"
  33. >
  34. <template v-slot:dialogText>
  35. <v-card-title class="text-h5 grey lighten-2">
  36. {{ $t('attention') }}
  37. </v-card-title>
  38. <v-card-text>
  39. <br>
  40. <p>{{ $t('quit_without_saving_warning') }}</p>
  41. </v-card-text>
  42. </template>
  43. <template v-slot:dialogBtn>
  44. <v-btn class="mr-4 submitBtn ot_green ot_white--text" @click="closeDialog">
  45. {{ $t('back_to_form') }}
  46. </v-btn>
  47. <v-btn class="mr-4 submitBtn ot_green ot_white--text" @click="saveAndQuit">
  48. {{ $t('save_and_quit') }}
  49. </v-btn>
  50. <v-btn class="mr-4 submitBtn ot_danger ot_white--text" @click="goEvenUnsavedData">
  51. {{ $t('quit_form') }}
  52. </v-btn>
  53. </template>
  54. </lazy-LayoutDialog>
  55. </main>
  56. </template>
  57. <script lang="ts">
  58. import { computed, defineComponent, onBeforeMount, onBeforeUnmount, onUnmounted, reactive, toRefs, useContext, watch, ref, Ref, ComputedRef } from '@nuxtjs/composition-api'
  59. import { Query } from '@vuex-orm/core'
  60. import { ToRefs, UnwrapRef } from '@vue/composition-api'
  61. import { repositoryHelper } from '~/services/store/repository'
  62. import { queryHelper } from '~/services/store/query'
  63. import { QUERY_TYPE, TYPE_ALERT } from '~/types/enums'
  64. import { alert, AnyJson } from '~/types/interfaces'
  65. import { $useDirtyForm } from '~/use/form/useDirtyForm'
  66. export default defineComponent({
  67. props: {
  68. model: {
  69. type: Function,
  70. required: true
  71. },
  72. id: {
  73. type: Number,
  74. required: true
  75. },
  76. query: {
  77. type: Object as () => Query,
  78. required: true
  79. }
  80. },
  81. setup (props) {
  82. const { $dataPersister, store, app: { router, i18n } } = useContext()
  83. const { markFormAsDirty, markFormAsNotDirty } = $useDirtyForm(store)
  84. const { id, query }:ToRefs = toRefs(props)
  85. const properties:UnwrapRef<AnyJson> = reactive({
  86. valid: false,
  87. saveOk: false,
  88. saveKo: false
  89. })
  90. const readOnly:Ref<boolean> = ref(false)
  91. const entry:ComputedRef<AnyJson> = computed(() => {
  92. return queryHelper.getFlattenEntry(query.value, id.value)
  93. })
  94. const updateRepository = (newValue: string, field: string) => {
  95. markFormAsDirty()
  96. repositoryHelper.updateStoreFromField(props.model, entry.value, newValue, field)
  97. }
  98. const submit = async () => {
  99. try {
  100. markFormAsNotDirty()
  101. await $dataPersister.invoke({
  102. type: QUERY_TYPE.MODEL,
  103. model: props.model,
  104. id: id.value
  105. })
  106. const alert:alert = {
  107. type: TYPE_ALERT.SUCCESS,
  108. message: i18n.t('saveSuccess') as string
  109. }
  110. store.commit('page/setAlert', alert)
  111. } catch (error) {
  112. const alert:alert = {
  113. type: TYPE_ALERT.ALERT,
  114. message: error.message
  115. }
  116. store.commit('page/setAlert', alert)
  117. }
  118. }
  119. const showDialog:ComputedRef<boolean> = computed(() => {
  120. return store.state.form.showConfirmToLeave
  121. })
  122. const closeDialog = () => {
  123. store.commit('form/setShowConfirmToLeave', false)
  124. }
  125. const saveAndQuit = async () => {
  126. await submit()
  127. goEvenUnsavedData()
  128. }
  129. const goEvenUnsavedData = () => {
  130. markFormAsNotDirty()
  131. store.commit('form/setShowConfirmToLeave', false)
  132. const entryCopy = query.value.first()
  133. if (entryCopy && entryCopy.$getAttributes().originalState) {
  134. repositoryHelper.persist(props.model, entryCopy.$getAttributes().originalState)
  135. }
  136. if (router) {
  137. router.push(store.state.form.goAfterLeave)
  138. }
  139. }
  140. return {
  141. submit,
  142. updateRepository,
  143. properties,
  144. readOnly,
  145. showDialog,
  146. entry,
  147. goEvenUnsavedData,
  148. closeDialog,
  149. saveAndQuit
  150. }
  151. }
  152. })
  153. </script>
  154. <style scoped>
  155. .btnActions {
  156. text-align: right;
  157. }
  158. </style>