import type { Ref } from 'vue' import type { ValidationResult } from '@/composables/validation/useValidation' import type { DateModelValue } from '@/composables/date/useDateInitializationDayjs' import { useManualDateValidation } from './useManualDateValidation' export interface UseDateTextFieldManualValidationOptions { required: boolean disableErrorHandling: boolean // eslint-disable-next-line @typescript-eslint/no-explicit-any customRules: any // eslint-disable-next-line @typescript-eslint/no-explicit-any customWarningRules: any hasInteracted: Ref errors: Ref clearValidation: () => void validateDateFormat: (dateStr: string) => { isValid: boolean, message: string } isDateComplete: (value: string) => boolean parseDate: (dateStr: string, format: string) => Date | null // eslint-disable-next-line @typescript-eslint/no-explicit-any validateField: (value: unknown, rules?: any[], warningRules?: any[]) => Promise } export interface UseDateTextFieldSubmitOptions { isValidating: Ref hasInteracted: Ref inputValue: Ref runRules: (value: string) => Promise } export interface UseDateTextFieldResetOptions { clearValidation: () => void isFocused: Ref hasInteracted: Ref isDisabled: () => boolean fieldKey: Ref isFormatting: Ref inputValue: Ref selectedDates: Ref resetState: () => void emitModel: (value: DateModelValue) => void } export interface UseDateTextFieldOptions { autoClamp: boolean isRange: Ref displayFormat: Ref autoClampDate: (dateStr: string, format: string) => { clampedDate: string, adjusted: boolean } manualValidation: UseDateTextFieldManualValidationOptions submit?: UseDateTextFieldSubmitOptions reset?: UseDateTextFieldResetOptions } /** * Composable de haut niveau pour la saisie de date dans un champ texte. * Pour l'instant il encapsule uniquement la logique d'autoClamp * afin de pouvoir être partagé entre les différents scénarios (single / range). */ export const useDateTextField = (options: UseDateTextFieldOptions) => { const { autoClamp, isRange, displayFormat, autoClampDate, manualValidation, submit, reset: resetOptions } = options const { validateManualInput } = useManualDateValidation({ format: displayFormat.value, required: manualValidation.required, disableErrorHandling: manualValidation.disableErrorHandling, customRules: manualValidation.customRules, customWarningRules: manualValidation.customWarningRules, hasInteracted: manualValidation.hasInteracted, errors: manualValidation.errors, clearValidation: manualValidation.clearValidation, validateDateFormat: manualValidation.validateDateFormat, isDateComplete: manualValidation.isDateComplete, parseDate: manualValidation.parseDate, // eslint-disable-next-line @typescript-eslint/no-explicit-any validateField: manualValidation.validateField as (value: unknown, rules?: any[], warningRules?: any[]) => Promise, }) const validateOnSubmit = async () => { if (!submit) return true const { isValidating, hasInteracted, inputValue, runRules } = submit isValidating.value = true hasInteracted.value = true const ok = await runRules(inputValue.value) isValidating.value = false return ok } const clampIfNeeded = (raw: string): string => { if (!autoClamp || !raw) return raw if (isRange.value && raw.includes(' - ')) { const [rawStartDate = '', rawEndDate = ''] = raw.split(' - ').map(dateText => dateText.trim()) const startDateValidation = rawStartDate ? autoClampDate(rawStartDate, displayFormat.value) : { adjusted: false, clampedDate: rawStartDate } const endDateValidation = rawEndDate ? autoClampDate(rawEndDate, displayFormat.value) : { adjusted: false, clampedDate: rawEndDate } const formattedStartDate = startDateValidation.clampedDate || '' const formattedEndDate = endDateValidation.clampedDate || '' return formattedEndDate ? `${formattedStartDate} - ${formattedEndDate}` : `${formattedStartDate} - ` } const dateValidationResult = autoClampDate(raw, displayFormat.value) return dateValidationResult.clampedDate } const reset = () => { if (!resetOptions) return const { clearValidation, isFocused, hasInteracted, isDisabled, fieldKey, isFormatting, inputValue, selectedDates, resetState, emitModel, } = resetOptions // 1) Nettoyer l'état de validation et d'interaction clearValidation() isFocused.value = false hasInteracted.value = false if (isDisabled()) { fieldKey.value++ return } // 2) Réinitialiser la valeur sans déclencher de validation interactive isFormatting.value = true inputValue.value = '' selectedDates.value = null resetState() isFormatting.value = false // 3) Synchroniser le modèle externe emitModel(null) // 4) Forcer la recréation du champ pour réinitialiser l'état interne de Vuetify fieldKey.value++ } return { clampIfNeeded, validateManualInput, validateOnSubmit, reset, } } export default useDateTextField