Event.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. <template>
  2. <LayoutCommonSection>
  3. <v-row>
  4. <v-col cols="12" sm="12">
  5. <h4 class="mb-8">{{ $t('general_informations') }}</h4>
  6. <UiInputText
  7. v-model="proxyEntity.name"
  8. field="name"
  9. :rules="getAsserts('name')"
  10. />
  11. <span class="label">{{ $t('datetimeStart') }}</span>
  12. <UiInputDateTimePicker
  13. :model-value="proxyEntity.datetimeStart"
  14. field="datetimeStart"
  15. label="datetimeStart"
  16. :with-time-picker="true"
  17. class="my-2"
  18. :rules="getAsserts('datetimeStart')"
  19. validate-on-blur
  20. @update:model-value="onUpdateDateTimeStart(proxyEntity, $event)"
  21. />
  22. <span class="label">{{ $t('datetimeEnd') }}</span>
  23. <UiInputDateTimePicker
  24. :model-value="proxyEntity.datetimeEnd"
  25. field="datetimeEnd"
  26. label="datetimeEnd"
  27. :with-time-picker="true"
  28. class="my-2"
  29. :rules="getAsserts('datetimeEnd')"
  30. @update:model-value="onUpdateDateTimeEnd(proxyEntity, $event)"
  31. />
  32. <span class="label">{{ $t('description') }}</span>
  33. <UiInputTextArea v-model="proxyEntity.description" class="mt-3" />
  34. <UiInputTreeSelectEventCategories
  35. v-model="proxyEntity.categories"
  36. label="event_categories_choices"
  37. />
  38. <UiInputImage
  39. v-model="proxyEntity.image"
  40. field="image"
  41. label="event_image"
  42. :width="240"
  43. :cropping-enabled="true"
  44. />
  45. </v-col>
  46. </v-row>
  47. </LayoutCommonSection>
  48. <LayoutCommonSection>
  49. <v-row>
  50. <v-col cols="12">
  51. <h4 class="mb-8">{{ $t('place_event') }}</h4>
  52. <UiInputAutocompleteApiResources
  53. v-if="!newPlace"
  54. v-model="proxyEntity.place"
  55. field="place"
  56. :model="PlaceSearchItem"
  57. list-value="id"
  58. list-label="name"
  59. @update:model-value="getPlace(proxyEntity)"
  60. />
  61. <v-row class="mb-6 justify-center">
  62. <v-col
  63. v-if="newPlace"
  64. cols="12"
  65. sm="6"
  66. class="d-flex justify-center mb-2"
  67. >
  68. <v-btn
  69. prepend-icon="fa-solid fa-cancel"
  70. @click="onCancelPlaceClick(proxyEntity)"
  71. >
  72. {{ $t('cancel') }}
  73. </v-btn>
  74. </v-col>
  75. <v-col
  76. v-if="proxyEntity.place && !editPlace"
  77. cols="12"
  78. sm="6"
  79. class="d-flex justify-center mb-2"
  80. >
  81. <v-btn
  82. prepend-icon="fa-solid fa-pencil"
  83. @click="onEditPlaceClick(proxyEntity)"
  84. >
  85. {{ $t('edit_place') }}
  86. </v-btn>
  87. </v-col>
  88. <v-col
  89. v-if="!newPlace"
  90. cols="12" sm="6" class="d-flex justify-center mb-2">
  91. <v-btn
  92. prepend-icon="fa-solid fa-plus"
  93. @click="onAddPlaceClick(proxyEntity)"
  94. >
  95. {{ $t('add_place') }}
  96. </v-btn>
  97. </v-col>
  98. </v-row>
  99. <UiInputText
  100. v-model="proxyEntity.placeName"
  101. :readonly="!newPlace && !editPlace"
  102. field="placeName"
  103. />
  104. <UiInputText
  105. v-model="proxyEntity.streetAddress"
  106. :readonly="!newPlace && !editPlace"
  107. field="streetAddress"
  108. />
  109. <UiInputText
  110. v-model="proxyEntity.streetAddressSecond"
  111. :readonly="!newPlace && !editPlace"
  112. field="streetAddressSecond"
  113. />
  114. <UiInputText
  115. v-model="proxyEntity.streetAddressThird"
  116. :readonly="!newPlace && !editPlace"
  117. field="streetAddressThird"
  118. />
  119. <UiInputText
  120. v-model="proxyEntity.postalCode"
  121. :readonly="!newPlace && !editPlace"
  122. field="postalCode"
  123. />
  124. <UiInputText
  125. v-model="proxyEntity.addressCity"
  126. :readonly="!newPlace && !editPlace"
  127. field="addressCity"
  128. />
  129. <UiInputAutocompleteApiResources
  130. v-model="proxyEntity.addressCountry"
  131. :readonly="!newPlace && !editPlace"
  132. field="addressCountry"
  133. :model="Country"
  134. list-value="id"
  135. list-label="name"
  136. />
  137. <client-only>
  138. <UiMapLeaflet
  139. v-model:latitude="proxyEntity.latitude"
  140. v-model:longitude="proxyEntity.longitude"
  141. :readonly="!newPlace && !editPlace"
  142. :street-address="proxyEntity.streetAddress"
  143. :street-address-second="proxyEntity.streetAddressSecond"
  144. :street-address-third="proxyEntity.streetAddressThird"
  145. :postal-code="proxyEntity.postalCode"
  146. :address-city="proxyEntity.addressCity"
  147. :address-country-id="proxyEntity.addressCountry"
  148. :search-button="true"
  149. ></UiMapLeaflet>
  150. </client-only>
  151. </v-col>
  152. </v-row>
  153. </LayoutCommonSection>
  154. <LayoutCommonSection>
  155. <v-row>
  156. <v-col cols="12">
  157. <h4 class="mb-8">{{ $t('communication_params') }}</h4>
  158. <UiInputText v-model="proxyEntity.url" field="url" :rules="getAsserts('url')" />
  159. <UiInputAutocompleteEnum
  160. v-model="proxyEntity.pricing"
  161. enum-name="pricing_event"
  162. field="pricing"
  163. />
  164. <UiInputText
  165. v-if="proxyEntity.pricing === 'PAID'"
  166. v-model="proxyEntity.urlTicket"
  167. :rules="getAsserts('urlTicket')"
  168. field="urlTicket"
  169. />
  170. <UiInputNumber
  171. v-if="proxyEntity.pricing === 'PAID'"
  172. v-model="proxyEntity.priceMini"
  173. field="priceMini"
  174. :rules="getAsserts('priceMini')"
  175. />
  176. <UiInputNumber
  177. v-if="proxyEntity.pricing === 'PAID'"
  178. v-model="proxyEntity.priceMaxi"
  179. field="priceMaxi"
  180. :rules="getAsserts('priceMaxi')"
  181. />
  182. </v-col>
  183. </v-row>
  184. </LayoutCommonSection>
  185. <LazyLayoutDialog :show="showAlert" theme="warning">
  186. <template #dialogType>{{ $t('important') }}</template>
  187. <template #dialogTitle>{{ $t('place_change_everywhere') }}</template>
  188. <template #dialogText>
  189. <v-card-text class="text">
  190. <p>
  191. {{ $t('warning_edit_place') }}
  192. </p>
  193. <br />
  194. <p>
  195. {{ $t('are_you_sure_to_process') }}
  196. </p>
  197. </v-card-text>
  198. </template>
  199. <template #dialogBtn>
  200. <v-btn class="mr-4 submitBtn theme-neutral-strong" @click="closeDialog">
  201. {{ $t('cancel') }}
  202. </v-btn>
  203. <v-btn class="mr-4 submitBtn theme-warning" @click="onEditPlaceConfirm">
  204. {{ $t('i_understand') }}
  205. </v-btn>
  206. </template>
  207. </LazyLayoutDialog>
  208. </template>
  209. <script setup lang="ts">
  210. import Event from '~/models/Freemium/Event'
  211. import Place from '~/models/Freemium/Place'
  212. import { getAssertUtils } from '~/services/asserts/getAssertUtils'
  213. import DateUtils from '~/services/utils/dateUtils'
  214. import Country from '~/models/Core/Country'
  215. import PlaceSearchItem from '~/models/Custom/Search/PlaceSearchItem'
  216. import { useEntityManager } from '~/composables/data/useEntityManager'
  217. const props = defineProps<{
  218. entity: Event
  219. }>()
  220. const { em } = useEntityManager()
  221. const getAsserts = (key) => getAssertUtils(Event.getAsserts(), key)
  222. const emit = defineEmits(['update:entity'])
  223. // Pour éviter l'erreur eslint "Unexpected mutation of "modelValue" prop"
  224. const proxyEntity = computed({
  225. get: () => props.entity,
  226. set: (value) => emit('update:entity', value),
  227. })
  228. /**
  229. * Si la date de début est mise à jour, on s'assure que la date de fin est
  230. * après elle, sinon elle devient égale
  231. * @param entity
  232. * @param dateTime
  233. */
  234. const onUpdateDateTimeStart = (entity, dateTime) => {
  235. if (DateUtils.isBefore(props.entity.datetimeEnd, dateTime, false)) {
  236. const dateTimeEnd = new Date(dateTime);
  237. // Ajouter 1h
  238. dateTimeEnd.setHours(dateTimeEnd.getHours() + 1);
  239. entity.datetimeEnd = DateUtils.toIsoUtcOffset(dateTimeEnd)
  240. }
  241. entity.datetimeStart = dateTime
  242. emit('update:entity', entity)
  243. }
  244. /**
  245. * Si la date de fin est mise à jour, on s'assure que la date de début est
  246. * avant elle, sinon elle devient égale
  247. * @param entity
  248. * @param dateTime
  249. */
  250. const onUpdateDateTimeEnd = (entity, dateTime) => {
  251. if (DateUtils.isBefore(dateTime, props.entity.datetimeStart, false)) {
  252. const dateTimeStart = new Date(dateTime);
  253. // Retirer 1h
  254. dateTimeStart.setHours(dateTimeStart.getHours() - 1);
  255. entity.datetimeStart = DateUtils.toIsoUtcOffset(dateTimeStart)
  256. }
  257. entity.datetimeEnd = dateTime
  258. emit('update:entity', entity)
  259. }
  260. const showAlert: Ref<boolean> = ref(false)
  261. const newPlace: Ref<boolean> = ref(false)
  262. const editPlace: Ref<boolean> = ref(false)
  263. /**
  264. * Si on clique sur le bouton "Ajouter un lieu", le choix dans la liste déroulante
  265. * est mise à nulle, et les champs input de l'adresse sont vidées
  266. * @param entity
  267. */
  268. const onAddPlaceClick = function (entity: Event) {
  269. newPlace.value = true
  270. entity.place = null
  271. resetPlace(entity)
  272. }
  273. const onCancelPlaceClick = function (entity: Event) {
  274. newPlace.value = false
  275. entity.place = null
  276. resetPlace(entity)
  277. }
  278. /**
  279. * Quand on clique sur le bouton "Editer le lieu", une alerte s'affiche.
  280. */
  281. const onEditPlaceClick = function () {
  282. showAlert.value = true
  283. }
  284. /**
  285. * Quand on ferme la boite de dialogue
  286. */
  287. const closeDialog = function () {
  288. showAlert.value = false
  289. }
  290. /**
  291. * Si on décide d'éditer le lieu
  292. */
  293. const onEditPlaceConfirm = function () {
  294. showAlert.value = false
  295. editPlace.value = true
  296. }
  297. /**
  298. * Lorsque l'on choisit un lieu dans la liste déroulante, on met à jour les champs
  299. * input de l'adresse
  300. * @param entity
  301. */
  302. const getPlace = async (entity: Event) => {
  303. if (entity.place) {
  304. const placeInstance = await em.fetch(Place, entity.place as number)
  305. entity.placeName = placeInstance.name
  306. entity.streetAddress = placeInstance.streetAddress
  307. entity.streetAddressSecond = placeInstance.streetAddressSecond
  308. entity.streetAddressThird = placeInstance.streetAddressThird
  309. entity.addressCity = placeInstance.addressCity
  310. entity.postalCode = placeInstance.postalCode
  311. entity.addressCountry = placeInstance.addressCountry
  312. entity.latitude = placeInstance.latitude
  313. entity.longitude = placeInstance.longitude
  314. editPlace.value = false
  315. } else {
  316. // Dans le cas où l'on ne récupère aucune place on remet à null le formulaire de l'adresse
  317. resetPlace(entity)
  318. }
  319. emit('update:entity', entity)
  320. }
  321. /**
  322. * fonction permettant de remettre à vide tous les champs input de l'adresse
  323. * @param entity
  324. */
  325. const resetPlace = (entity: Event) => {
  326. entity.placeName = null
  327. entity.streetAddress = null
  328. entity.streetAddressSecond = null
  329. entity.streetAddressThird = null
  330. entity.addressCity = null
  331. entity.postalCode = null
  332. entity.addressCountry = null
  333. entity.latitude = null
  334. entity.longitude = null
  335. }
  336. // Nettoyer les données lors du démontage du composant
  337. onBeforeUnmount(() => {
  338. // Nettoyer les références du store si nécessaire
  339. if (import.meta.client) {
  340. clearNuxtData('/^' + Place.entity + '_/')
  341. useRepo(Place).flush()
  342. }
  343. })
  344. </script>
  345. <style scoped lang="scss">
  346. .label {
  347. font-size: 16px;
  348. color: rgb(var(--v-theme-on-primary-alt));
  349. }
  350. </style>