attendances.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <LayoutContainer>
  3. <div v-if="organizationProfile.isSchool">
  4. <UiLoadingPanel v-if="pending" />
  5. <UiForm
  6. v-else-if="parameters !== null"
  7. :model="Parameters"
  8. :entity="parameters"
  9. action-position="bottom"
  10. >
  11. <v-row>
  12. <v-col cols="12">
  13. <UiInputCheckbox
  14. v-model="parameters.sendAttendanceEmail"
  15. field="sendAttendanceEmail"
  16. label="sendAttendanceEmail"
  17. />
  18. <UiInputCheckbox
  19. v-model="parameters.sendAttendanceSms"
  20. field="sendAttendanceSms"
  21. />
  22. <UiInputCheckbox
  23. v-model="parameters.notifyAdministrationAbsence"
  24. field="notifyAdministrationAbsence"
  25. />
  26. <UiInputNumber
  27. v-model="parameters.numberConsecutiveAbsences"
  28. field="notifyAdministrationAbsence"
  29. :rules="rules()"
  30. />
  31. </v-col>
  32. </v-row>
  33. </UiForm>
  34. <v-divider class="my-10" />
  35. </div>
  36. <UiLoadingPanel v-if="attendanceBookingReasonsPending" />
  37. <div v-else>
  38. <v-table>
  39. <thead>
  40. <tr>
  41. <td>{{ $t('attendanceBookingReasons') }}</td>
  42. <td></td>
  43. </tr>
  44. </thead>
  45. <tbody v-if="attendanceBookingReasons.length > 0">
  46. <tr v-for="reason in attendanceBookingReasons" :key="reason.id">
  47. <td class="cycle-editable-cell">
  48. {{ reason.reason }}
  49. </td>
  50. <td class="d-flex flex-row">
  51. <v-btn
  52. :flat="true"
  53. icon="fa fa-pen"
  54. class="cycle-edit-icon mr-3"
  55. @click="goToEditPage(reason.id as number)"
  56. />
  57. <UiButtonDelete
  58. :model="AttendanceBookingReason"
  59. :entity="reason"
  60. :flat="true"
  61. class="cycle-edit-icon"
  62. />
  63. </td>
  64. </tr>
  65. </tbody>
  66. <tbody v-else>
  67. <tr class="theme-neutral">
  68. <td>
  69. <i>{{ $t('nothing_to_show') }}</i>
  70. </td>
  71. <td></td>
  72. </tr>
  73. </tbody>
  74. </v-table>
  75. <v-btn
  76. :flat="true"
  77. prepend-icon="fa fa-plus"
  78. class="theme-primary mt-4"
  79. @click="goToCreatePage"
  80. >
  81. {{ $t('add') }}
  82. </v-btn>
  83. </div>
  84. </LayoutContainer>
  85. </template>
  86. <script setup lang="ts">
  87. import type { AsyncData } from '#app'
  88. import { type Collection, useRepo } from 'pinia-orm'
  89. import type { ComputedRef } from 'vue'
  90. import Parameters from '~/models/Organization/Parameters'
  91. import { useEntityFetch } from '~/composables/data/useEntityFetch'
  92. import { useOrganizationProfileStore } from '~/stores/organizationProfile'
  93. import UrlUtils from '~/services/utils/urlUtils'
  94. import AttendanceBookingReason from '~/models/Booking/AttendanceBookingReason'
  95. import AttendanceBookingReasonRepository from '~/stores/repositories/AttendanceBookingReasonRepository'
  96. definePageMeta({
  97. name: 'parameters_attendances_page',
  98. })
  99. const { fetch } = useEntityFetch()
  100. const i18n = useI18n()
  101. const organizationProfile = useOrganizationProfileStore()
  102. if (organizationProfile.parametersId === null) {
  103. throw new Error('Missing organization parameters id')
  104. }
  105. const { data: parameters, pending } = fetch(
  106. Parameters,
  107. organizationProfile.parametersId,
  108. ) as AsyncData<Parameters | null, Error | null>
  109. const { fetchCollection } = useEntityFetch()
  110. const { pending: attendanceBookingReasonsPending } = fetchCollection(
  111. AttendanceBookingReason,
  112. )
  113. const attendanceBookingReasonsRepo = useRepo(AttendanceBookingReasonRepository)
  114. const rules = () => [
  115. (numberConsecutiveAbsences: string | null) =>
  116. (numberConsecutiveAbsences !== null &&
  117. parseInt(numberConsecutiveAbsences) > 0) ||
  118. i18n.t('please_enter_a_value'),
  119. ]
  120. /**
  121. * On récupère les timings via le store
  122. * (sans ça, les mises à jour SSE ne seront pas prises en compte)
  123. */
  124. const attendanceBookingReasons: ComputedRef<
  125. Collection<AttendanceBookingReason>
  126. > = computed(() => {
  127. return attendanceBookingReasonsRepo.getReasons()
  128. })
  129. const goToEditPage = (id: number) => {
  130. navigateTo(UrlUtils.join('/parameters/attendance_booking_reasons', id))
  131. }
  132. const goToCreatePage = () => {
  133. navigateTo('/parameters/attendance_booking_reasons/new')
  134. }
  135. </script>