|
|
@@ -1,66 +1,47 @@
|
|
|
<!--
|
|
|
Sélecteur de dates
|
|
|
-
|
|
|
-@see https://vuetifyjs.com/en/components/date-pickers/
|
|
|
-->
|
|
|
|
|
|
<template>
|
|
|
<main>
|
|
|
- <v-text-field
|
|
|
- ref="input"
|
|
|
- v-model="datesFormatted"
|
|
|
- autocomplete="off"
|
|
|
- :label="$t(fieldLabel)"
|
|
|
- prepend-icon="mdi:mdi-calendar"
|
|
|
- :disabled="readonly"
|
|
|
- :density="dense ? 'compact' : 'default'"
|
|
|
- :single-line="singleLine"
|
|
|
- :error="error || !!fieldViolations"
|
|
|
- :error-messages="errorMessage || fieldViolations ? $t(fieldViolations) : ''"
|
|
|
- @update:focused=""
|
|
|
- @focus="onInputFocused($event); $emit('focus', $event)"
|
|
|
- @blur="onInputBlured($event); $emit('blur', $event)"
|
|
|
- />
|
|
|
-
|
|
|
- <v-menu
|
|
|
- activator="input"
|
|
|
- :model-value="dateOpen"
|
|
|
- :close-on-content-click="false"
|
|
|
- :nudge-right="40"
|
|
|
- transition="scale-transition"
|
|
|
- offset-y
|
|
|
- min-width="auto"
|
|
|
- >
|
|
|
- <!-- TODO: terminer une fois v-date-picker implémenté dans vuetify 3 -->
|
|
|
- <v-date-picker
|
|
|
- v-model="datesParsed"
|
|
|
- :range="range"
|
|
|
- color="primary lighten-1"
|
|
|
- @input="dateOpen = range && datesParsed.length < 2"
|
|
|
+ <div class="d-flex flex-column">
|
|
|
+ <span>{{ $t(fieldLabel) }}</span>
|
|
|
+
|
|
|
+ <UiDatePicker
|
|
|
+ v-model="date"
|
|
|
+ :readonly="readonly"
|
|
|
+ :format="format"
|
|
|
+ @update:model-value="onUpdate($event)"
|
|
|
+ @change="onChange($event)"
|
|
|
/>
|
|
|
- </v-menu>
|
|
|
+
|
|
|
+ <span v-if="error || !!fieldViolations" class="theme-danger">
|
|
|
+ {{ errorMessage || fieldViolations ? $t(fieldViolations) : '' }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
</main>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import {useFieldViolation} from "~/composables/form/useFieldViolation";
|
|
|
-import {computed, ComputedRef, Ref} from "@vue/reactivity";
|
|
|
-import DateUtils from "~/services/utils/dateUtils";
|
|
|
-import {onUnmounted, watch, WatchStopHandle} from "@vue/runtime-core";
|
|
|
+import {formatISO} from "date-fns";
|
|
|
|
|
|
const props = defineProps({
|
|
|
- field: {
|
|
|
+ /**
|
|
|
+ * v-model
|
|
|
+ */
|
|
|
+ modelValue: {
|
|
|
type: String,
|
|
|
required: false,
|
|
|
default: null
|
|
|
},
|
|
|
- label: {
|
|
|
+ field: {
|
|
|
type: String,
|
|
|
required: false,
|
|
|
default: null
|
|
|
},
|
|
|
- data: {
|
|
|
- type: [String, Array],
|
|
|
+ label: {
|
|
|
+ type: String,
|
|
|
required: false,
|
|
|
default: null
|
|
|
},
|
|
|
@@ -68,22 +49,10 @@ const props = defineProps({
|
|
|
type: Boolean,
|
|
|
required: false
|
|
|
},
|
|
|
- range: {
|
|
|
- type: Boolean,
|
|
|
- required: false
|
|
|
- },
|
|
|
- dense: {
|
|
|
- type: Boolean,
|
|
|
- required: false
|
|
|
- },
|
|
|
- singleLine: {
|
|
|
- type: Boolean,
|
|
|
- required: false
|
|
|
- },
|
|
|
format: {
|
|
|
type: String,
|
|
|
required: false,
|
|
|
- default: 'DD/MM/YYYY'
|
|
|
+ default: null
|
|
|
},
|
|
|
error: {
|
|
|
type: Boolean,
|
|
|
@@ -98,55 +67,23 @@ const props = defineProps({
|
|
|
|
|
|
const input = ref(null)
|
|
|
|
|
|
-const { emit } = useNuxtApp()
|
|
|
-
|
|
|
-const { data, range } = props
|
|
|
-
|
|
|
const {fieldViolations, updateViolationState} = useFieldViolation(props.field)
|
|
|
|
|
|
-const datesParsed: Ref<Array<string>|string|null> = range ? ref(Array<string>()) : ref(null)
|
|
|
-
|
|
|
const fieldLabel = props.label ?? props.field
|
|
|
|
|
|
-const dateOpen: Ref<boolean> = ref(false)
|
|
|
+const emit = defineEmits(['update:model-value', 'change'])
|
|
|
|
|
|
-const onInputFocused = (event: any) => {
|
|
|
- dateOpen.value = true
|
|
|
-}
|
|
|
+const date: Ref<Date> = ref(new Date(props.modelValue))
|
|
|
+console.log(date.value)
|
|
|
|
|
|
-const onInputBlured = (event: any) => {
|
|
|
- dateOpen.value = false
|
|
|
+const onUpdate = (event: string) => {
|
|
|
+ emit('update:model-value', formatISO(date.value))
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-if (Array.isArray(datesParsed.value)) {
|
|
|
- for (const date of data as Array<string>) {
|
|
|
- if (date) {
|
|
|
- datesParsed.value.push(DateUtils.format(date, 'YYYY-MM-DD'))
|
|
|
- }
|
|
|
- }
|
|
|
-} else {
|
|
|
- datesParsed.value = data ? DateUtils.format(data, 'YYYY-MM-DD') : null
|
|
|
+const onChange = (event: Event | undefined) => {
|
|
|
+ updateViolationState(event)
|
|
|
+ emit('change', formatISO(date.value))
|
|
|
}
|
|
|
-
|
|
|
-const datesFormatted: ComputedRef<string|null> = computed(() => {
|
|
|
- if (props.range && datesParsed.value && datesParsed.value.length < 2) {
|
|
|
- return null
|
|
|
- }
|
|
|
- return datesParsed.value ? DateUtils.formatAndConcat(datesParsed.value, props.format) : null
|
|
|
-})
|
|
|
-
|
|
|
-const unwatch: WatchStopHandle = watch(datesParsed, (newValue, oldValue) => {
|
|
|
- if (newValue === oldValue) { return }
|
|
|
- if (props.range && newValue && newValue.length < 2) { return }
|
|
|
- updateViolationState(Array.isArray(newValue) ? DateUtils.sort(newValue) : newValue)
|
|
|
-})
|
|
|
-
|
|
|
-onUnmounted(() => {
|
|
|
- unwatch()
|
|
|
-})
|
|
|
-
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|