Browse Source

refact date picker and parameters page minor fixes

Olivier Massot 9 tháng trước cách đây
mục cha
commit
39ec76a22d

+ 2 - 1
components/Layout/SubHeader/DataTimingRange.vue

@@ -5,9 +5,10 @@
         {{ $t('period_choose') }}
       </span>
 
-      <UiDateRangePicker
+      <UiDatePicker
         :model-value="datesRange"
         :max-height="28"
+        :range="true"
         @update:model-value="updateDateTimeRange"
       />
     </div>

+ 116 - 95
components/Ui/DatePicker.vue

@@ -1,119 +1,140 @@
 <!--
-Sélecteur de dates avec Vuetify
+Sélecteur de dates
 
-@see https://vuetifyjs.com/en/components/date-pickers/
+@see https://vue3datepicker.com/
 -->
 
 <template>
-  <v-layout row wrap>
-    <!--
-    TODO: remplacer par <v-date-input> quand celui ci ne sera plus expérimental
-    (@see https://vuetifyjs.com/en/components/date-inputs)
-    -->
-    <v-menu
-      v-model="menu"
-      :close-on-content-click="false"
-      :nudge-right="40"
-      lazy
-      transition="scale-transition"
-      offset-y
-      :max-width="290"
-      :min-width="290"
-      :position-x="positionX"
-      :position-y="positionY"
-    >
-      <template #activator="{ props: attrs }">
-        <v-text-field
-          v-model="displayDate"
-          :label="label"
-          :readonly="true"
-          v-bind="attrs"
-          prepend-inner-icon="far fa-calendar"
-          variant="outlined"
-          density="compact"
-        />
-      </template>
-
-      <v-date-picker
-        :model-value="modelValue"
-        :locale="i18n.locale.value"
-        no-title
-        scrollable
-        @update:model-value="updateDate"
-      />
-    </v-menu>
-  </v-layout>
+  <VueDatePicker
+    :model-value="modelValue"
+    :locale="locale"
+    :format="dateFormatPattern"
+    :format-locale="fnsLocale"
+    :range="range"
+    :multi-calendars="range"
+    :enable-time-picker="withTimePicker"
+    :auto-apply="autoApply"
+    :auto-position="true"
+    :start-date="today"
+    close-on-scroll
+    text-input
+    :readonly="readonly"
+    position="left"
+    :teleport="true"
+    :select-text="$t('select')"
+    :cancel-text="$t('cancel')"
+    input-class-name="date-picker-input"
+    class="date-picker"
+    :style="style"
+    @update:model-value="$emit('update:modelValue', $event)"
+  />
 </template>
 
 <script setup lang="ts">
-import { ref, computed, nextTick, watch, type PropType } from 'vue'
 import { useI18n } from 'vue-i18n'
+import DateUtils, { supportedLocales } from '~/services/utils/dateUtils'
+import type { PropType } from '@vue/runtime-core';
+import type { Locale } from 'date-fns';
 
 const props = defineProps({
-  modelValue: Date,
-  label: {
-    type: String,
-    default: '',
-  },
-  format: {
-    type: String,
+  modelValue: {
+    type: Object as PropType<Date | Array<Date> | null>,
+    required: false,
     default: null,
   },
-  /**
-   * Position du date-picker
-   * @see https://vuetifyjs.com/en/api/v-menu/#props-position
-   */
-  position: {
-    type: String as PropType<'left' | 'center' | 'right'>,
-    default: 'center',
+  range: {
+    type: Boolean,
+    default: false,
+  },
+  withTimePicker: {
+    type: Boolean,
+    default: false,
+  },
+  autoApply: {
+    type: Boolean,
+    default: true,
   },
+  maxHeight: {
+    type: Number,
+    required: false,
+    default: null,
+  },
+  readonly: {
+    type: Boolean,
+    default: false,
+  }
 })
 
-const emit = defineEmits(['update:modelValue'])
-
 const i18n = useI18n()
-const menu = ref(false)
-const positionX = ref(0)
-const positionY = ref(0)
-
-const displayDate = computed({
-  get: () => {
-    if (!props.modelValue) return ''
-    if (props.format) {
-      return new Intl.DateTimeFormat(i18n.locale.value, {
-        year: 'numeric',
-        month: '2-digit',
-        day: '2-digit',
-      }).format(props.modelValue)
-    }
-    return props.modelValue.toLocaleDateString(i18n.locale.value)
-  },
-  set: () => {},
-})
 
-function updateDate(value: Date) {
-  emit('update:modelValue', value)
-  menu.value = false
-}
+const locale: Ref<string> = i18n.locale
 
-function updatePosition() {
-  nextTick(() => {
-    const activator = document.querySelector('.v-menu__activator')
-    if (activator) {
-      const rect = activator.getBoundingClientRect()
-      positionX.value = rect.left
-      positionY.value = rect.bottom
-    }
-  })
-}
+const fnsLocale: ComputedRef<Locale> = computed(
+  () => DateUtils.getFnsLocale(locale.value as supportedLocales)
+)
 
-watch(menu, (val) => {
-  if (val) updatePosition()
-})
+const dateFormatPattern: ComputedRef<string> = computed(
+  () => DateUtils.getShortFormatPattern(locale.value as supportedLocales)
+)
+
+const today = new Date()
+
+let style: ComputedRef<string> = computed(
+  () => props.maxHeight !== null ? 'height: ' + props.maxHeight + 'px;max-height: ' + props.maxHeight + 'px;' : ''
+)
 </script>
 
-<style scoped>
-.v-menu__content {
-  position: absolute !important;
+<style scoped lang="scss">
+// @see https://vue3datepicker.com/customization/theming/
+// [!] Sass variables overriding does not work in scoped mode
+.dp__theme_light,
+.dp__theme_dark {
+  --dp-background-color: #ffffff;
+  --dp-text-color: #212121;
+  --dp-hover-color: #f3f3f3;
+  --dp-hover-text-color: #212121;
+  --dp-hover-icon-color: #959595;
+  --dp-primary-color: rgb(var(--v-theme-primary)) !important;
+  --dp-primary-text-color: rgb(var(--v-theme-on-primary)) !important;
+  --dp-secondary-color: rgb(var(--v-theme-neutral-strong)) !important;
+  --dp-border-color: #ddd;
+  --dp-menu-border-color: #ddd;
+  --dp-border-color-hover: #aaaeb7;
+  --dp-disabled-color: #f6f6f6;
+  --dp-scroll-bar-background: #f3f3f3;
+  --dp-scroll-bar-color: #959595;
+  --dp-success-color: rgb(var(--v-theme-success)) !important;
+  --dp-success-color-disabled: rgb(var(--v-theme-neutral-strong)) !important;
+  --dp-icon-color: #959595;
+  --dp-danger-color: #ff6f60;
+  --dp-highlight-color: rgba(25, 118, 210, 0.1);
+}
+
+.date-picker {
+  div {
+    height: 100% !important;
+    max-height: 100% !important;
+  }
+
+  .dp__input_wrap {
+    height: 100% !important;
+    max-height: 100% !important;
+  }
+
+  .date-picker-input {
+    height: 100% !important;
+    max-height: 100% !important;
+  }
+
+  :deep(.dp__active_date) {
+    border-radius: 12px;
+  }
+
+  :deep(.dp__today) {
+    border-radius: 12px;
+    border: 1px solid rgb(var(--v-theme-neutral-strong)) !important;
+  }
 }
+
+
 </style>

+ 0 - 129
components/Ui/DateRangePicker.vue

@@ -1,129 +0,0 @@
-<template>
-  <!-- @see https://vue3datepicker.com/props/modes/#multi-calendars -->
-  <VueDatePicker
-    :model-value="modelValue"
-    range
-    multi-calendars
-    :auto-apply="autoApply"
-    :locale="i18n.locale.value"
-    :format-locale="fnsLocale"
-    :format="dateFormatPattern"
-    :start-date="today"
-    :teleport="true"
-    :alt-position="dateRangePickerAltPosition"
-    :enable-time-picker="false"
-    close-on-scroll
-    text-input
-    :select-text="$t('select')"
-    :cancel-text="$t('cancel')"
-    input-class-name="date-range-picker-input"
-    @update:model-value="updateDateTimeRange"
-    class="date-range-picker"
-    :style="style"
-  />
-</template>
-
-<script setup lang="ts">
-import DateUtils, { supportedLocales } from '~/services/utils/dateUtils'
-import type { PropType } from '@vue/runtime-core'
-
-const props = defineProps({
-  modelValue: {
-    type: Array as PropType<Array<Date> | null>,
-    required: false,
-    default: null,
-  },
-  maxHeight: {
-    type: Number,
-    required: false,
-    default: null,
-  },
-})
-
-const emit = defineEmits(['update:modelValue'])
-
-const autoApply = false
-
-const updateDateTimeRange = (value: [string, string]) => {
-  emit('update:modelValue', value)
-}
-
-const i18n = useI18n()
-
-const fnsLocale = DateUtils.getFnsLocale(i18n.locale.value as supportedLocales)
-const dateFormatPattern = DateUtils.getShortFormatPattern(
-  i18n.locale.value as supportedLocales,
-)
-
-const today = new Date()
-
-let style = ''
-if (props.maxHeight !== null) {
-  style +=
-    'height: ' + props.maxHeight + 'px;max-height: ' + props.maxHeight + 'px;'
-}
-
-/**
- * Recalcule la position du panneau de sélection des dates si trop près du bord droit de l'écran
- * @param el
- */
-const dateRangePickerAltPosition = (el: HTMLElement) => {
-  let xOffset = 0
-  const fullWidth = 500
-  const rightPadding = 30
-  const rect = el.getBoundingClientRect()
-
-  if (rect.left + fullWidth + rightPadding > window.innerWidth) {
-    xOffset = window.innerWidth - (rect.left + fullWidth + rightPadding)
-  }
-
-  return {
-    top: rect.bottom,
-    left: rect.left + xOffset,
-  }
-}
-</script>
-
-<style lang="scss">
-// @see https://vue3datepicker.com/customization/theming/
-// [!] Sass variables overriding does not work in scoped mode
-.dp__theme_light,
-.dp__theme_dark {
-  --dp-background-color: #ffffff;
-  --dp-text-color: #212121;
-  --dp-hover-color: #f3f3f3;
-  --dp-hover-text-color: #212121;
-  --dp-hover-icon-color: #959595;
-  --dp-primary-color: rgb(var(--v-theme-primary)) !important;
-  --dp-primary-text-color: rgb(var(--v-theme-on-primary)) !important;
-  --dp-secondary-color: rgb(var(--v-theme-neutral-strong)) !important;
-  --dp-border-color: #ddd;
-  --dp-menu-border-color: #ddd;
-  --dp-border-color-hover: #aaaeb7;
-  --dp-disabled-color: #f6f6f6;
-  --dp-scroll-bar-background: #f3f3f3;
-  --dp-scroll-bar-color: #959595;
-  --dp-success-color: rgb(var(--v-theme-success)) !important;
-  --dp-success-color-disabled: rgb(var(--v-theme-neutral-strong)) !important;
-  --dp-icon-color: #959595;
-  --dp-danger-color: #ff6f60;
-  --dp-highlight-color: rgba(25, 118, 210, 0.1);
-}
-
-.date-range-picker {
-  div {
-    height: 100% !important;
-    max-height: 100% !important;
-  }
-
-  .dp__input_wrap {
-    height: 100% !important;
-    max-height: 100% !important;
-  }
-
-  .date-range-picker-input {
-    height: 100% !important;
-    max-height: 100% !important;
-  }
-}
-</style>

+ 1 - 20
components/Ui/Input/DatePicker.vue

@@ -8,10 +8,8 @@ Sélecteur de dates, à placer dans un composant `UiForm`
       <span>{{ $t(fieldLabel) }}</span>
 
       <UiDatePicker
-        v-model="date"
+        :model-value="date"
         :readonly="readonly"
-        :format="format"
-        :position="position"
         @update:model-value="onUpdate($event)"
       />
 
@@ -63,15 +61,6 @@ const props = defineProps({
     type: Boolean,
     required: false,
   },
-  /**
-   * Format d'affichage des dates
-   * @see https://vue3datepicker.com/props/formatting/
-   */
-  format: {
-    type: String,
-    required: false,
-    default: null,
-  },
   /**
    * Règles de validation
    * @see https://vuetify.cn/en/components/forms/#validation-with-submit-clear
@@ -96,14 +85,6 @@ const props = defineProps({
     required: false,
     default: null,
   },
-  /**
-   * @see https://vue3datepicker.com/props/positioning/#position
-   */
-  position: {
-    type: String as PropType<'left' | 'center' | 'right'>,
-    required: false,
-    default: 'center',
-  },
 })
 
 const { fieldViolations, updateViolationState } = useFieldViolation(props.field)

+ 1 - 1
package.json

@@ -32,7 +32,7 @@
     "@nuxtjs/i18n": "^9.1.3",
     "@pinia-orm/nuxt": "^1.10.1",
     "@pinia/nuxt": "^0.5.1",
-    "@vuepic/vue-datepicker": "^7.4.0",
+    "@vuepic/vue-datepicker": "^11.0",
     "cleave.js": "^1.6.0",
     "date-fns": "^4.1.0",
     "event-source-polyfill": "^1.0.31",

+ 19 - 19
pages/parameters/general_parameters.vue

@@ -18,31 +18,18 @@
 
           <UiInputDatePicker
             v-if="organizationProfile.isSchool"
-            v-model="parameters.startCourseDate"
-            field="startCourseDate"
-            label="start_date_of_courses"
+            v-model="parameters.musicalDate"
+            field="musicalDate"
+            label="start_date_of_activity_season"
             position="left"
             class="my-2"
           />
 
-          <UiInputCheckbox
-            v-model="parameters.showAdherentList"
-            field="showAdherentList"
-            label="show_adherents_list_and_their_coordinates"
-          />
-
-          <UiInputAutocompleteWithEnum
-            v-model="parameters.timezone"
-            enum-name="timezone"
-            field="timezone"
-            variant="underlined"
-          />
-
           <UiInputDatePicker
             v-if="organizationProfile.isSchool"
-            v-model="parameters.musicalDate"
-            field="musicalDate"
-            label="start_date_of_activity_season"
+            v-model="parameters.startCourseDate"
+            field="startCourseDate"
+            label="start_date_of_courses"
             position="left"
             class="my-2"
           />
@@ -56,6 +43,19 @@
             class="my-2"
           />
 
+          <UiInputAutocompleteWithEnum
+            v-model="parameters.timezone"
+            enum-name="timezone"
+            field="timezone"
+            variant="underlined"
+          />
+
+          <UiInputCheckbox
+            v-model="parameters.showAdherentList"
+            field="showAdherentList"
+            label="show_adherents_list_and_their_coordinates"
+          />
+
           <UiInputCheckbox
             v-if="
               organizationProfile.isSchool && organizationProfile.isAssociation

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 301 - 258
yarn.lock


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác