@cnamts/synapse 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{DateFilter-BmRuzQ9Z.js → DateFilter-YWOTbfeL.js} +1 -1
- package/dist/{NumberFilter-CnIPDHqx.js → NumberFilter-DMmMgALM.js} +1 -1
- package/dist/{PeriodFilter-CZwZ8CnQ.js → PeriodFilter-Bok5BHcn.js} +1 -1
- package/dist/SelectFilter-BKud2WhN.js +136 -0
- package/dist/{TextFilter-DTxZHJwX.js → TextFilter-DvMf2thH.js} +1 -1
- package/dist/components/Accordion/Accordion.d.ts +2 -1
- package/dist/components/Accordion/composables/useAccordionGroupCommunication.d.ts +5 -0
- package/dist/components/Accordion/composables/useAccordionKeyboardNavigation.d.ts +12 -0
- package/dist/components/Accordion/composables/useAccordionState.d.ts +13 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +85 -0
- package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +2 -0
- package/dist/components/Customs/SySelect/SySelect.d.ts +33 -13
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +2 -2
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +1585 -1452
- package/dist/components/DatePicker/DatePicker/DatePicker.d.ts +16 -2
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +3 -1
- package/dist/components/DatePicker/composables/index.d.ts +2 -0
- package/dist/components/DatePicker/composables/useAsteriskDisplay.d.ts +14 -0
- package/dist/components/DatePicker/composables/useDateAutoClamp.d.ts +16 -0
- package/dist/components/DatePicker/composables/useDateRangeInput.d.ts +1 -1
- package/dist/components/DatePicker/composables/useDisplayedDateString.d.ts +3 -0
- package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +1 -0
- package/dist/components/DatePicker/composables/useMonthButtonCustomization.d.ts +5 -2
- package/dist/components/NirField/NirField.d.ts +7 -3
- package/dist/components/NirField/nirValidation.d.ts +1 -1
- package/dist/components/PasswordField/PasswordField.d.ts +2 -0
- package/dist/components/PeriodField/PeriodField.d.ts +52 -8
- package/dist/components/PhoneField/PhoneField.d.ts +2 -2
- package/dist/components/RangeField/RangeField.d.ts +2 -0
- package/dist/components/SearchListField/SearchListField.d.ts +9 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +2 -0
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +14 -9
- package/dist/components/Tables/SyTable/SyTable.d.ts +12 -7
- package/dist/components/Tables/common/SyTablePagination.d.ts +1636 -0
- package/dist/components/Tables/common/TableHeader.d.ts +2 -20
- package/dist/components/Tables/common/filters/SelectFilter.d.ts +5 -5
- package/dist/components/Tables/common/filters/getFilterComponent.d.ts +1 -0
- package/dist/components/Tables/common/filters/locales.d.ts +4 -0
- package/dist/components/Tables/common/filters/logics/date.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/number.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/period.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/select.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/text.d.ts +1 -0
- package/dist/components/Tables/common/locales.d.ts +21 -0
- package/dist/components/Tables/common/organizeColumns/OrganizeColumns.d.ts +267 -0
- package/dist/components/Tables/common/organizeColumns/sortHeaders.d.ts +2 -0
- package/dist/components/Tables/common/tableFilterUtils.d.ts +1 -0
- package/dist/components/Tables/common/tableStorageUtils.d.ts +41 -1
- package/dist/components/Tables/common/tableUtils.d.ts +42 -5
- package/dist/components/Tables/common/types.d.ts +19 -8
- package/dist/components/Tables/common/usePagination.d.ts +22 -0
- package/dist/components/Tables/common/useTableCheckbox.d.ts +20 -0
- package/dist/components/Tables/common/useTableHeaders.d.ts +76 -0
- package/dist/components/Tables/common/useTableItems.d.ts +24 -0
- package/dist/components/Tables/common/useTableOptions.d.ts +18 -0
- package/dist/components/ToolbarContainer/ToolbarContainer.d.ts +11 -0
- package/dist/components/UserMenuBtn/UserMenuBtn.d.ts +9 -2
- package/dist/components/index.d.ts +8 -6
- package/dist/design-system-v3.js +58 -56
- package/dist/design-system-v3.umd.cjs +22 -22
- package/dist/main-Cx8qG7YR.js +16344 -0
- package/dist/stories/Accessibilite/Vuetify/VuetifyItems.d.ts +14 -2
- package/dist/stories/DesignTokens/StylesTypographiques.stories.new.d.ts +8 -0
- package/dist/stories/DesignTokens/TypographyDisplay.d.ts +28 -0
- package/dist/stories/DesignTokens/vue-shims.d.ts +6 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/common/imgs/accessibility-svgrepo-com.svg +4 -0
- package/src/components/Accordion/Accessibilite/AccessibilityGuide.mdx +249 -0
- package/src/components/Accordion/Accordion.vue +48 -76
- package/src/components/Accordion/composables/__tests__/useAccordionGroupCommunication.spec.ts +146 -0
- package/src/components/Accordion/composables/__tests__/useAccordionKeyboardNavigation.spec.ts +209 -0
- package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +144 -0
- package/src/components/Accordion/composables/useAccordionGroupCommunication.ts +52 -0
- package/src/components/Accordion/composables/useAccordionKeyboardNavigation.ts +111 -0
- package/src/components/Accordion/composables/useAccordionState.ts +59 -0
- package/src/components/Accordion/tests/__snapshots__/accordion.spec.ts.snap +3 -0
- package/src/components/Customs/SyCheckbox/Accessibilite.mdx +303 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +50 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +630 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +326 -0
- package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +201 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +1 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +8 -1
- package/src/components/Customs/SySelect/SySelect.stories.ts +160 -0
- package/src/components/Customs/SySelect/SySelect.vue +291 -32
- package/src/components/Customs/SySelect/tests/SySelect.spec.ts +230 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +3 -2
- package/src/components/Customs/SyTextField/SyTextField.vue +19 -8
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +241 -31
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +305 -57
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.events.spec.ts +161 -0
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +4 -2
- package/src/components/DatePicker/DatePicker/DatePicker.stories.ts +259 -137
- package/src/components/DatePicker/DatePicker/DatePicker.vue +153 -25
- package/src/components/DatePicker/DatePicker/tests/DatePicker.events.spec.ts +189 -0
- package/src/components/DatePicker/DatePicker/{DatePicker.spec.ts → tests/DatePicker.spec.ts} +1 -15
- package/src/components/DatePicker/DateTextInput/DateRange.stories.ts +24 -14
- package/src/components/DatePicker/DateTextInput/DateTextInput.events.spec.ts +148 -0
- package/src/components/DatePicker/DateTextInput/DateTextInput.spec.ts +3 -1
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +200 -5
- package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +241 -31
- package/src/components/DatePicker/composables/index.ts +2 -0
- package/src/components/DatePicker/composables/tests/useDateAutoClamp.spec.ts +190 -0
- package/src/components/DatePicker/composables/tests/useInputBlurHandler.spec.ts +182 -4
- package/src/components/DatePicker/composables/tests/useMonthButtonCustomization.spec.ts +105 -80
- package/src/components/DatePicker/composables/useAsteriskDisplay.ts +31 -0
- package/src/components/DatePicker/composables/useDateAutoClamp.ts +136 -0
- package/src/components/DatePicker/composables/useDateRangeInput.ts +21 -18
- package/src/components/DatePicker/composables/useDisplayedDateString.ts +13 -1
- package/src/components/DatePicker/composables/useInputBlurHandler.ts +84 -20
- package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +149 -51
- package/src/components/DiacriticPicker/DiacriticPicker.stories.ts +10 -0
- package/src/components/ErrorPage/Accessibilite.stories.ts +8 -0
- package/src/components/ErrorPage/ErrorPage.vue +12 -6
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +4 -4
- package/src/components/NirField/NirField.mdx +22 -9
- package/src/components/NirField/NirField.stories.ts +26 -2
- package/src/components/NirField/NirField.vue +209 -22
- package/src/components/NirField/nirValidation.ts +17 -3
- package/src/components/NirField/tests/NirField.spec.ts +2 -2
- package/src/components/NotFoundPage/Accessibilite.stories.ts +8 -0
- package/src/components/NotFoundPage/NotFoundPage.vue +2 -1
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +8 -6
- package/src/components/PaginatedTable/PaginatedTable.mdx +2 -0
- package/src/components/PasswordField/PasswordField.stories.ts +4 -0
- package/src/components/PasswordField/PasswordField.vue +3 -0
- package/src/components/PeriodField/PeriodField.vue +2 -0
- package/src/components/PhoneField/PhoneField.stories.ts +15 -15
- package/src/components/PhoneField/PhoneField.vue +1 -1
- package/src/components/RangeField/RangeField.stories.ts +9 -0
- package/src/components/RangeField/RangeField.vue +4 -0
- package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +12 -0
- package/src/components/SearchListField/SearchListField.vue +5 -0
- package/src/components/SyTextArea/SyTextArea.vue +3 -0
- package/src/components/SyTextArea/tests/SyTextArea.spec.ts +0 -1
- package/src/components/Tables/SyServerTable/FilterRules.stories.ts +632 -15
- package/src/components/Tables/SyServerTable/SyServerTable.mdx +15 -5
- package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +2844 -1377
- package/src/components/Tables/SyServerTable/SyServerTable.vue +155 -66
- package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +256 -4
- package/src/components/Tables/SyTable/FilterRules.stories.ts +183 -0
- package/src/components/Tables/SyTable/SyTable.mdx +14 -4
- package/src/components/Tables/SyTable/SyTable.stories.ts +1265 -477
- package/src/components/Tables/SyTable/SyTable.vue +152 -72
- package/src/components/Tables/SyTable/tests/SyTable.spec.ts +366 -4
- package/src/components/Tables/common/SyTableFilter.vue +3 -56
- package/src/components/Tables/common/SyTablePagination.vue +375 -0
- package/src/components/Tables/common/TableHeader.vue +10 -26
- package/src/components/Tables/common/filters/SelectFilter.vue +131 -22
- package/src/components/Tables/common/filters/getFilterComponent.ts +54 -0
- package/src/components/Tables/common/filters/locales.ts +4 -0
- package/src/components/Tables/common/filters/logics/date.ts +12 -0
- package/src/components/Tables/common/filters/logics/number.ts +48 -0
- package/src/components/Tables/common/filters/logics/period.ts +25 -0
- package/src/components/Tables/common/filters/logics/select.ts +27 -0
- package/src/components/Tables/common/filters/logics/tests/TextFilterLogic.spec.ts +177 -0
- package/src/components/Tables/common/filters/logics/text.ts +62 -0
- package/src/components/Tables/common/filters/tests/TextFilter.spec.ts +11 -11
- package/src/components/Tables/common/locales.ts +24 -0
- package/src/components/Tables/common/organizeColumns/OrganizeColumns.vue +269 -0
- package/src/components/Tables/common/organizeColumns/sortHeaders.ts +9 -0
- package/src/components/Tables/common/tableFilterUtils.ts +43 -295
- package/src/components/Tables/common/tableStorageUtils.ts +27 -2
- package/src/components/Tables/common/tableStyles.scss +26 -0
- package/src/components/Tables/common/tableUtils.ts +3 -16
- package/src/components/Tables/common/tests/SyTablePagination.spec.ts +170 -0
- package/src/components/Tables/common/tests/filterByRange.spec.ts +215 -0
- package/src/components/Tables/common/tests/tableFilterUtils.spec.ts +0 -14
- package/src/components/Tables/common/tests/tableUtils.spec.ts +7 -51
- package/src/components/Tables/common/types.ts +17 -6
- package/src/components/Tables/common/usePagination.ts +83 -0
- package/src/components/Tables/common/useTableCheckbox.ts +58 -0
- package/src/components/Tables/common/useTableHeaders.ts +88 -0
- package/src/components/Tables/common/useTableItems.ts +87 -0
- package/src/components/Tables/common/useTableOptions.ts +93 -0
- package/src/components/ToolbarContainer/ToolbarContainer.mdx +16 -0
- package/src/components/ToolbarContainer/ToolbarContainer.stories.ts +675 -0
- package/src/components/ToolbarContainer/ToolbarContainer.vue +128 -0
- package/src/components/ToolbarContainer/tests/ToolbarContainer.spec.ts +156 -0
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +74 -0
- package/src/components/UserMenuBtn/UserMenuBtn.vue +19 -17
- package/src/components/index.ts +8 -6
- package/src/stories/Accessibilite/Aculturation/AuditDesignSystem.mdx +293 -20
- package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +448 -54
- package/src/stories/Accessibilite/Audit/RGAA.mdx +231 -23
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +591 -7
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +139 -38
- package/src/stories/Accessibilite/Introduction.mdx +258 -18
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +221 -31
- package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +204 -22
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +537 -24
- package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +577 -70
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru.mdx +382 -31
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +419 -81
- package/src/stories/Accessibilite/Vuetify/Vuetify.mdx +132 -6
- package/src/stories/Accessibilite/Vuetify/Vuetify.stories.ts +370 -146
- package/src/stories/Accessibilite/Vuetify/VuetifyItems.ts +35 -57
- package/src/stories/Demarrer/Accueil.stories.ts +20 -5
- package/src/stories/DesignTokens/StylesTypographiques.mdx +10 -9
- package/src/stories/DesignTokens/StylesTypographiques.stories.new.ts +397 -0
- package/src/stories/DesignTokens/StylesTypographiques.stories.ts +397 -0
- package/src/stories/DesignTokens/TypographyDisplay.vue +155 -0
- package/src/stories/DesignTokens/vue-shims.d.ts +6 -0
- package/src/stories/GuideDuDev/LesBreackingChanges.mdx +0 -2
- package/src/stories/GuideDuDev/MigrationDepuisBridge.mdx +1 -1
- package/src/stories/GuideDuDev/MigrationDepuisVue2.mdx +1 -1
- package/src/stories/GuideDuDev/PortailAgent.mdx +10 -0
- package/src/stories/GuideDuDev/PortailAgent.stories.ts +506 -0
- package/src/stories/GuideDuDev/Theme.mdx +41 -0
- package/dist/SelectFilter-Cj-GW2Cc.js +0 -97
- package/dist/main-WDqeoGM-.js +0 -14788
- package/src/components/PaginatedTable/tests/__snapshots__/PaginatedTable.spec.ts.snap +0 -886
- package/src/components/Tables/SyServerTable/tests/__snapshots__/SyServerTable.spec.ts.snap +0 -521
- package/src/components/Tables/SyTable/tests/__snapshots__/SyTable.spec.ts.snap +0 -521
- package/src/stories/DesignTokens/ThemePA.mdx +0 -35
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
2
|
import { ref } from 'vue'
|
|
3
3
|
import { useInputBlurHandler } from '../useInputBlurHandler'
|
|
4
|
+
import { DATE_PICKER_MESSAGES } from '../../constants/messages'
|
|
4
5
|
|
|
5
6
|
describe('useInputBlurHandler', () => {
|
|
6
7
|
// Mocks et setup
|
|
@@ -15,6 +16,7 @@ describe('useInputBlurHandler', () => {
|
|
|
15
16
|
const isManualInputActive = ref(true)
|
|
16
17
|
const isUpdatingFromInternal = ref(false)
|
|
17
18
|
const selectedDates = ref<Date | Date[] | null>(null)
|
|
19
|
+
const errors = ref<string[]>([])
|
|
18
20
|
|
|
19
21
|
beforeEach(() => {
|
|
20
22
|
// Réinitialiser les mocks et les refs avant chaque test
|
|
@@ -29,6 +31,7 @@ describe('useInputBlurHandler', () => {
|
|
|
29
31
|
isManualInputActive.value = true
|
|
30
32
|
isUpdatingFromInternal.value = false
|
|
31
33
|
selectedDates.value = null
|
|
34
|
+
errors.value = []
|
|
32
35
|
|
|
33
36
|
// Configuration par défaut des mocks
|
|
34
37
|
mockValidateDateFormat.mockReturnValue({ isValid: true, message: '' })
|
|
@@ -229,8 +232,15 @@ describe('useInputBlurHandler', () => {
|
|
|
229
232
|
expect(mockUpdateModel).not.toHaveBeenCalled()
|
|
230
233
|
})
|
|
231
234
|
|
|
232
|
-
it('devrait
|
|
235
|
+
it('devrait valider la date et mettre à jour le modèle avec la valeur formatée', () => {
|
|
233
236
|
displayFormattedDate.value = '01/01/2023'
|
|
237
|
+
// Simuler une date valide
|
|
238
|
+
mockValidateDateFormat.mockReturnValue({ isValid: true, message: '' })
|
|
239
|
+
const parsedDate = new Date('2023-01-01')
|
|
240
|
+
mockParseDate.mockReturnValue(parsedDate)
|
|
241
|
+
// Simuler le formatage de la date
|
|
242
|
+
const formattedDate = '01/01/2023'
|
|
243
|
+
mockFormatDate.mockReturnValue(formattedDate)
|
|
234
244
|
|
|
235
245
|
const { handleInputBlur } = useInputBlurHandler({
|
|
236
246
|
format: 'DD/MM/YYYY',
|
|
@@ -239,6 +249,7 @@ describe('useInputBlurHandler', () => {
|
|
|
239
249
|
isManualInputActive,
|
|
240
250
|
isUpdatingFromInternal,
|
|
241
251
|
selectedDates,
|
|
252
|
+
errors,
|
|
242
253
|
validateDateFormat: mockValidateDateFormat,
|
|
243
254
|
parseDate: mockParseDate,
|
|
244
255
|
formatDate: mockFormatDate,
|
|
@@ -249,10 +260,13 @@ describe('useInputBlurHandler', () => {
|
|
|
249
260
|
|
|
250
261
|
handleInputBlur()
|
|
251
262
|
|
|
252
|
-
|
|
263
|
+
// Avec nos modifications, on valide d'abord le format de la date
|
|
264
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('01/01/2023')
|
|
265
|
+
// Puis on met à jour le modèle avec la date formatée (pas l'objet Date)
|
|
266
|
+
expect(mockUpdateModel).toHaveBeenCalledWith(formattedDate)
|
|
253
267
|
})
|
|
254
268
|
|
|
255
|
-
it('devrait
|
|
269
|
+
it('devrait mettre à jour le modèle avec null si displayFormattedDate est vide', () => {
|
|
256
270
|
displayFormattedDate.value = ''
|
|
257
271
|
|
|
258
272
|
const { handleInputBlur } = useInputBlurHandler({
|
|
@@ -262,6 +276,168 @@ describe('useInputBlurHandler', () => {
|
|
|
262
276
|
isManualInputActive,
|
|
263
277
|
isUpdatingFromInternal,
|
|
264
278
|
selectedDates,
|
|
279
|
+
errors,
|
|
280
|
+
validateDateFormat: mockValidateDateFormat,
|
|
281
|
+
parseDate: mockParseDate,
|
|
282
|
+
formatDate: mockFormatDate,
|
|
283
|
+
updateModel: mockUpdateModel,
|
|
284
|
+
validateManualInput: mockValidateManualInput,
|
|
285
|
+
emitBlur: mockEmitBlur,
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
handleInputBlur()
|
|
289
|
+
|
|
290
|
+
// Avec nos modifications, on met à jour directement le modèle avec null
|
|
291
|
+
// au lieu d'appeler validateManualInput
|
|
292
|
+
expect(mockUpdateModel).toHaveBeenCalledWith(null)
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
// Nouveaux tests pour les plages de dates
|
|
297
|
+
describe('handleInputBlur avec plages de dates', () => {
|
|
298
|
+
it('devrait mettre à jour le modèle avec un tableau de dates si la plage est valide', () => {
|
|
299
|
+
displayFormattedDate.value = '01/01/2023 - 10/01/2023'
|
|
300
|
+
const startDate = new Date('2023-01-01')
|
|
301
|
+
const endDate = new Date('2023-01-10')
|
|
302
|
+
|
|
303
|
+
mockValidateDateFormat
|
|
304
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de début
|
|
305
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de fin
|
|
306
|
+
|
|
307
|
+
mockParseDate
|
|
308
|
+
.mockReturnValueOnce(startDate) // Pour la date de début
|
|
309
|
+
.mockReturnValueOnce(endDate) // Pour la date de fin
|
|
310
|
+
|
|
311
|
+
mockFormatDate
|
|
312
|
+
.mockReturnValueOnce('01/01/2023') // Pour la date de début
|
|
313
|
+
.mockReturnValueOnce('10/01/2023') // Pour la date de fin
|
|
314
|
+
|
|
315
|
+
const { handleInputBlur } = useInputBlurHandler({
|
|
316
|
+
format: 'DD/MM/YYYY',
|
|
317
|
+
displayFormattedDate,
|
|
318
|
+
hasInteracted,
|
|
319
|
+
isManualInputActive,
|
|
320
|
+
isUpdatingFromInternal,
|
|
321
|
+
selectedDates,
|
|
322
|
+
errors,
|
|
323
|
+
validateDateFormat: mockValidateDateFormat,
|
|
324
|
+
parseDate: mockParseDate,
|
|
325
|
+
formatDate: mockFormatDate,
|
|
326
|
+
updateModel: mockUpdateModel,
|
|
327
|
+
validateManualInput: mockValidateManualInput,
|
|
328
|
+
emitBlur: mockEmitBlur,
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
handleInputBlur()
|
|
332
|
+
|
|
333
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('01/01/2023')
|
|
334
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('10/01/2023')
|
|
335
|
+
expect(mockParseDate).toHaveBeenCalledWith('01/01/2023', 'DD/MM/YYYY')
|
|
336
|
+
expect(mockParseDate).toHaveBeenCalledWith('10/01/2023', 'DD/MM/YYYY')
|
|
337
|
+
expect(mockFormatDate).toHaveBeenCalledWith(startDate, 'DD/MM/YYYY')
|
|
338
|
+
expect(mockFormatDate).toHaveBeenCalledWith(endDate, 'DD/MM/YYYY')
|
|
339
|
+
expect(selectedDates.value).toEqual([startDate, endDate])
|
|
340
|
+
expect(mockUpdateModel).toHaveBeenCalledWith(['01/01/2023', '10/01/2023'])
|
|
341
|
+
expect(isUpdatingFromInternal.value).toBe(true) // Sera réinitialisé par le setTimeout
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
it('devrait utiliser le format de retour pour les plages de dates si spécifié', () => {
|
|
345
|
+
displayFormattedDate.value = '01/01/2023 - 10/01/2023'
|
|
346
|
+
const startDate = new Date('2023-01-01')
|
|
347
|
+
const endDate = new Date('2023-01-10')
|
|
348
|
+
|
|
349
|
+
mockValidateDateFormat
|
|
350
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de début
|
|
351
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de fin
|
|
352
|
+
|
|
353
|
+
mockParseDate
|
|
354
|
+
.mockReturnValueOnce(startDate) // Pour la date de début
|
|
355
|
+
.mockReturnValueOnce(endDate) // Pour la date de fin
|
|
356
|
+
|
|
357
|
+
mockFormatDate
|
|
358
|
+
.mockReturnValueOnce('2023-01-01') // Pour la date de début avec format de retour
|
|
359
|
+
.mockReturnValueOnce('2023-01-10') // Pour la date de fin avec format de retour
|
|
360
|
+
|
|
361
|
+
const { handleInputBlur } = useInputBlurHandler({
|
|
362
|
+
format: 'DD/MM/YYYY',
|
|
363
|
+
dateFormatReturn: 'YYYY-MM-DD',
|
|
364
|
+
displayFormattedDate,
|
|
365
|
+
hasInteracted,
|
|
366
|
+
isManualInputActive,
|
|
367
|
+
isUpdatingFromInternal,
|
|
368
|
+
selectedDates,
|
|
369
|
+
errors,
|
|
370
|
+
validateDateFormat: mockValidateDateFormat,
|
|
371
|
+
parseDate: mockParseDate,
|
|
372
|
+
formatDate: mockFormatDate,
|
|
373
|
+
updateModel: mockUpdateModel,
|
|
374
|
+
validateManualInput: mockValidateManualInput,
|
|
375
|
+
emitBlur: mockEmitBlur,
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
handleInputBlur()
|
|
379
|
+
|
|
380
|
+
expect(mockFormatDate).toHaveBeenCalledWith(startDate, 'YYYY-MM-DD')
|
|
381
|
+
expect(mockFormatDate).toHaveBeenCalledWith(endDate, 'YYYY-MM-DD')
|
|
382
|
+
expect(mockUpdateModel).toHaveBeenCalledWith(['2023-01-01', '2023-01-10'])
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('devrait ajouter une erreur si la date de fin est antérieure à la date de début', () => {
|
|
386
|
+
displayFormattedDate.value = '10/01/2023 - 01/01/2023' // Date de fin avant date de début
|
|
387
|
+
const startDate = new Date('2023-01-10')
|
|
388
|
+
const endDate = new Date('2023-01-01')
|
|
389
|
+
|
|
390
|
+
mockValidateDateFormat
|
|
391
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de début
|
|
392
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de fin
|
|
393
|
+
|
|
394
|
+
mockParseDate
|
|
395
|
+
.mockReturnValueOnce(startDate) // Pour la date de début
|
|
396
|
+
.mockReturnValueOnce(endDate) // Pour la date de fin
|
|
397
|
+
|
|
398
|
+
// Utiliser la constante importée au début du fichier
|
|
399
|
+
|
|
400
|
+
const { handleInputBlur } = useInputBlurHandler({
|
|
401
|
+
format: 'DD/MM/YYYY',
|
|
402
|
+
displayFormattedDate,
|
|
403
|
+
hasInteracted,
|
|
404
|
+
isManualInputActive,
|
|
405
|
+
isUpdatingFromInternal,
|
|
406
|
+
selectedDates,
|
|
407
|
+
errors,
|
|
408
|
+
validateDateFormat: mockValidateDateFormat,
|
|
409
|
+
parseDate: mockParseDate,
|
|
410
|
+
formatDate: mockFormatDate,
|
|
411
|
+
updateModel: mockUpdateModel,
|
|
412
|
+
validateManualInput: mockValidateManualInput,
|
|
413
|
+
emitBlur: mockEmitBlur,
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
handleInputBlur()
|
|
417
|
+
|
|
418
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('10/01/2023')
|
|
419
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('01/01/2023')
|
|
420
|
+
expect(mockParseDate).toHaveBeenCalledWith('10/01/2023', 'DD/MM/YYYY')
|
|
421
|
+
expect(mockParseDate).toHaveBeenCalledWith('01/01/2023', 'DD/MM/YYYY')
|
|
422
|
+
expect(errors.value).toContain(DATE_PICKER_MESSAGES.ERROR_END_BEFORE_START)
|
|
423
|
+
expect(mockUpdateModel).not.toHaveBeenCalled()
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
it('ne devrait pas mettre à jour le modèle si une des dates de la plage est invalide', () => {
|
|
427
|
+
displayFormattedDate.value = '01/01/2023 - 32/01/2023' // Date de fin invalide
|
|
428
|
+
|
|
429
|
+
mockValidateDateFormat
|
|
430
|
+
.mockReturnValueOnce({ isValid: true, message: '' }) // Pour la date de début
|
|
431
|
+
.mockReturnValueOnce({ isValid: false, message: 'Date invalide' }) // Pour la date de fin
|
|
432
|
+
|
|
433
|
+
const { handleInputBlur } = useInputBlurHandler({
|
|
434
|
+
format: 'DD/MM/YYYY',
|
|
435
|
+
displayFormattedDate,
|
|
436
|
+
hasInteracted,
|
|
437
|
+
isManualInputActive,
|
|
438
|
+
isUpdatingFromInternal,
|
|
439
|
+
selectedDates,
|
|
440
|
+
errors,
|
|
265
441
|
validateDateFormat: mockValidateDateFormat,
|
|
266
442
|
parseDate: mockParseDate,
|
|
267
443
|
formatDate: mockFormatDate,
|
|
@@ -272,7 +448,9 @@ describe('useInputBlurHandler', () => {
|
|
|
272
448
|
|
|
273
449
|
handleInputBlur()
|
|
274
450
|
|
|
275
|
-
expect(
|
|
451
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('01/01/2023')
|
|
452
|
+
expect(mockValidateDateFormat).toHaveBeenCalledWith('32/01/2023')
|
|
453
|
+
expect(mockUpdateModel).not.toHaveBeenCalled()
|
|
276
454
|
})
|
|
277
455
|
})
|
|
278
456
|
})
|
|
@@ -1,100 +1,125 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { ref, nextTick, type Ref } from 'vue'
|
|
2
3
|
import { useMonthButtonCustomization } from '../useMonthButtonCustomization'
|
|
3
|
-
import { nextTick } from 'vue'
|
|
4
|
-
|
|
5
|
-
// Mock pour nextTick
|
|
6
|
-
vi.mock('vue', async () => {
|
|
7
|
-
const actual = await vi.importActual('vue')
|
|
8
|
-
return {
|
|
9
|
-
...actual as object,
|
|
10
|
-
nextTick: vi.fn((callback) => {
|
|
11
|
-
if (callback) callback()
|
|
12
|
-
return Promise.resolve()
|
|
13
|
-
}),
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
4
|
|
|
17
5
|
describe('useMonthButtonCustomization', () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const mockYearBtn = {
|
|
25
|
-
innerHTML: '',
|
|
26
|
-
}
|
|
6
|
+
let isPickerVisibleGetter: () => boolean
|
|
7
|
+
// Définir explicitement le type pour éviter les erreurs de compatibilité
|
|
8
|
+
let monthName: Ref<string | null>
|
|
9
|
+
let yearName: Ref<string | null>
|
|
27
10
|
|
|
28
11
|
beforeEach(() => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (selector === '.v-date-picker-controls__mode-btn') {
|
|
41
|
-
return mockYearBtn
|
|
42
|
-
}
|
|
43
|
-
if (selector === '.v-date-picker-controls') {
|
|
44
|
-
return { childList: true, subtree: true }
|
|
45
|
-
}
|
|
46
|
-
return null
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// Mock pour MutationObserver
|
|
50
|
-
global.MutationObserver = vi.fn().mockImplementation(function (this: { observe: () => void, disconnect: () => void, callback: (mutations: MutationRecord[], observer: MutationObserver) => void }, callback) {
|
|
51
|
-
this.observe = vi.fn()
|
|
52
|
-
this.disconnect = vi.fn()
|
|
53
|
-
// Stocker le callback pour pouvoir le déclencher dans les tests
|
|
54
|
-
this.callback = callback
|
|
55
|
-
})
|
|
12
|
+
// Réinitialiser les refs pour chaque test avec le type exact attendu par le composable
|
|
13
|
+
monthName = ref<string | null>(null)
|
|
14
|
+
yearName = ref<string | null>(null)
|
|
15
|
+
|
|
16
|
+
document.body.innerHTML = `
|
|
17
|
+
<div class="v-date-picker-controls">
|
|
18
|
+
<button class="v-date-picker-controls__month-btn">janvier 2023</button>
|
|
19
|
+
<button class="v-date-picker-controls__mode-btn">2023</button>
|
|
20
|
+
</div>
|
|
21
|
+
`
|
|
22
|
+
isPickerVisibleGetter = () => true
|
|
56
23
|
})
|
|
57
24
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const { customizeMonthButton, setupMonthButtonObserver } = useMonthButtonCustomization(isPickerVisible)
|
|
61
|
-
expect(customizeMonthButton).toBeDefined()
|
|
62
|
-
expect(setupMonthButtonObserver).toBeDefined()
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
document.body.innerHTML = ''
|
|
63
27
|
})
|
|
64
28
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
customizeMonthButton(
|
|
69
|
-
|
|
29
|
+
// Test de l'affichage des mois personnalisés via les noms de mois fournis
|
|
30
|
+
it('personnalise correctement les noms de mois (janvier -> Janv.)', async () => {
|
|
31
|
+
monthName.value = 'janvier'
|
|
32
|
+
const { customizeMonthButton } = useMonthButtonCustomization(
|
|
33
|
+
isPickerVisibleGetter,
|
|
34
|
+
monthName,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
await customizeMonthButton()
|
|
38
|
+
await nextTick()
|
|
39
|
+
|
|
40
|
+
const monthBtn = document.querySelector('.v-date-picker-controls__month-btn')!
|
|
41
|
+
expect(monthBtn.textContent).toContain('Janv.')
|
|
70
42
|
})
|
|
71
43
|
|
|
72
|
-
it('
|
|
73
|
-
|
|
74
|
-
const { customizeMonthButton } = useMonthButtonCustomization(
|
|
44
|
+
it('personnalise correctement les noms de mois (février -> Févr.)', async () => {
|
|
45
|
+
monthName.value = 'février'
|
|
46
|
+
const { customizeMonthButton } = useMonthButtonCustomization(
|
|
47
|
+
isPickerVisibleGetter,
|
|
48
|
+
monthName,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
await customizeMonthButton()
|
|
52
|
+
await nextTick()
|
|
75
53
|
|
|
76
|
-
|
|
77
|
-
expect(
|
|
78
|
-
// Vérifier que le contenu du bouton a été modifié
|
|
79
|
-
expect(mockMonthBtn.innerHTML).not.toBe('')
|
|
80
|
-
expect(mockMonthBtn.innerHTML).toContain('Janvier')
|
|
54
|
+
const monthBtn = document.querySelector('.v-date-picker-controls__month-btn')!
|
|
55
|
+
expect(monthBtn.textContent).toContain('Févr.')
|
|
81
56
|
})
|
|
82
57
|
|
|
83
|
-
it('
|
|
84
|
-
|
|
85
|
-
const {
|
|
58
|
+
it('capitalise le premier caractère si le mois n\'est pas reconnu', async () => {
|
|
59
|
+
monthName.value = 'pluviose'
|
|
60
|
+
const { customizeMonthButton } = useMonthButtonCustomization(
|
|
61
|
+
isPickerVisibleGetter,
|
|
62
|
+
monthName,
|
|
63
|
+
)
|
|
86
64
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
65
|
+
await customizeMonthButton()
|
|
66
|
+
await nextTick()
|
|
67
|
+
|
|
68
|
+
const monthBtn = document.querySelector('.v-date-picker-controls__month-btn')!
|
|
69
|
+
expect(monthBtn.textContent).toContain('Pluviose')
|
|
91
70
|
})
|
|
92
71
|
|
|
93
|
-
it('
|
|
94
|
-
|
|
95
|
-
|
|
72
|
+
it('customise les boutons du mois et de l’année', async () => {
|
|
73
|
+
// S'assurer que monthName est null pour ce test
|
|
74
|
+
monthName.value = null
|
|
75
|
+
|
|
76
|
+
const { customizeMonthButton, monthButtonText } = useMonthButtonCustomization(
|
|
77
|
+
isPickerVisibleGetter,
|
|
78
|
+
monthName,
|
|
79
|
+
yearName,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
await customizeMonthButton()
|
|
83
|
+
await nextTick()
|
|
84
|
+
|
|
85
|
+
const monthBtn = document.querySelector('.v-date-picker-controls__month-btn')!
|
|
86
|
+
const yearBtn = document.querySelector('.v-date-picker-controls__mode-btn')!
|
|
87
|
+
|
|
88
|
+
expect(monthBtn.innerHTML).toContain('<svg') // icône ajoutée
|
|
89
|
+
expect(monthBtn.textContent).toContain('Janv.') // mois transformé
|
|
90
|
+
expect(monthButtonText.value).toBe('janvier 2023')
|
|
91
|
+
|
|
92
|
+
expect(yearBtn.innerHTML).toContain('2023')
|
|
93
|
+
expect(yearBtn.innerHTML).toContain('<svg')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('utilise monthName et yearName si fournis', async () => {
|
|
97
|
+
monthName.value = 'mars'
|
|
98
|
+
yearName.value = '2030'
|
|
99
|
+
|
|
100
|
+
const { customizeMonthButton } = useMonthButtonCustomization(
|
|
101
|
+
isPickerVisibleGetter,
|
|
102
|
+
monthName,
|
|
103
|
+
yearName,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
await customizeMonthButton()
|
|
107
|
+
await nextTick()
|
|
108
|
+
|
|
109
|
+
const monthBtn = document.querySelector('.v-date-picker-controls__month-btn')!
|
|
110
|
+
const yearBtn = document.querySelector('.v-date-picker-controls__mode-btn')!
|
|
111
|
+
|
|
112
|
+
expect(monthBtn.textContent).toContain('Mars')
|
|
113
|
+
expect(yearBtn.textContent).toContain('2030')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('observe les changements du DOM et personnalise automatiquement', async () => {
|
|
117
|
+
const { setupMonthButtonObserver } = useMonthButtonCustomization(() => true)
|
|
118
|
+
const spy = vi.spyOn(document, 'querySelectorAll')
|
|
119
|
+
|
|
120
|
+
setupMonthButtonObserver()
|
|
121
|
+
await nextTick()
|
|
96
122
|
|
|
97
|
-
|
|
98
|
-
expect(monthButtonText.value).toBe('Janvier 2025')
|
|
123
|
+
expect(spy).toHaveBeenCalledWith('.v-date-picker-controls')
|
|
99
124
|
})
|
|
100
125
|
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { computed } from 'vue'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Composable pour gérer l'affichage d'un astérisque à côté du label
|
|
5
|
+
* @param props - Les propriétés du composant contenant displayAsterisk et required
|
|
6
|
+
* @param labelProp - Le nom de la propriété contenant le label (par défaut: 'label')
|
|
7
|
+
* @returns Un objet contenant isShouldDisplayAsterisk et labelWithAsterisk
|
|
8
|
+
*/
|
|
9
|
+
export const useAsteriskDisplay = (
|
|
10
|
+
props: { displayAsterisk?: boolean, required?: boolean, [key: string]: unknown },
|
|
11
|
+
labelProp = 'label',
|
|
12
|
+
) => {
|
|
13
|
+
// Détermine si l'astérisque doit être affiché
|
|
14
|
+
const isShouldDisplayAsterisk = computed(() => {
|
|
15
|
+
return props.displayAsterisk && props.required
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
// Ajoute l'astérisque au label si nécessaire
|
|
19
|
+
const labelWithAsterisk = computed(() => {
|
|
20
|
+
// Assertion de type pour indiquer que props[labelProp] est de type string | undefined
|
|
21
|
+
const label = props[labelProp] as string | undefined
|
|
22
|
+
return isShouldDisplayAsterisk.value && label
|
|
23
|
+
? `${label} *`
|
|
24
|
+
: label
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
isShouldDisplayAsterisk,
|
|
29
|
+
labelWithAsterisk,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import dayjs from 'dayjs'
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
|
3
|
+
|
|
4
|
+
// Initialiser les plugins dayjs
|
|
5
|
+
dayjs.extend(customParseFormat)
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Composable pour gérer l'auto-clamping des dates invalides
|
|
9
|
+
* Cette fonctionnalité permet de ramener automatiquement les dates invalides
|
|
10
|
+
* (comme le 29/02 sur une année non bissextile ou 33/12) au dernier jour valide du mois
|
|
11
|
+
*/
|
|
12
|
+
export const useDateAutoClamp = () => {
|
|
13
|
+
/**
|
|
14
|
+
* Ajuste une date pour qu'elle soit valide en ramenant les jours invalides
|
|
15
|
+
* au dernier jour du mois correspondant
|
|
16
|
+
*
|
|
17
|
+
* @param day - Le jour à ajuster
|
|
18
|
+
* @param month - Le mois (0-11)
|
|
19
|
+
* @param year - L'année
|
|
20
|
+
* @returns Un objet contenant le jour ajusté et un booléen indiquant si un ajustement a été fait
|
|
21
|
+
*/
|
|
22
|
+
const clampDayToValidDate = (day: number, month: number, year: number): { day: number, adjusted: boolean } => {
|
|
23
|
+
// Vérifier si le jour est valide pour ce mois et cette année
|
|
24
|
+
// Créer une date pour le premier jour du mois et obtenir le nombre de jours dans ce mois
|
|
25
|
+
const dateObj = dayjs(`${year}-${month + 1}-01`)
|
|
26
|
+
const daysInMonth = dateObj.daysInMonth()
|
|
27
|
+
|
|
28
|
+
// Si le jour est supérieur au nombre de jours dans le mois, le ramener au dernier jour du mois
|
|
29
|
+
if (day > daysInMonth) {
|
|
30
|
+
return { day: daysInMonth, adjusted: true }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { day, adjusted: false }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Ajuste une date complète pour qu'elle soit valide
|
|
38
|
+
*
|
|
39
|
+
* @param dateStr - La chaîne de date à ajuster
|
|
40
|
+
* @param format - Le format de la date (ex: 'DD/MM/YYYY')
|
|
41
|
+
* @returns Un objet contenant la date ajustée et un booléen indiquant si un ajustement a été fait
|
|
42
|
+
*/
|
|
43
|
+
const autoClampDate = (dateStr: string, format: string): { clampedDate: string, adjusted: boolean } => {
|
|
44
|
+
// Si la chaîne est vide, retourner telle quelle
|
|
45
|
+
if (!dateStr) {
|
|
46
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Déterminer le séparateur utilisé dans le format
|
|
50
|
+
const separator = format.match(/[^DMY]/)?.[0] || '/'
|
|
51
|
+
|
|
52
|
+
// Extraire les parties du format pour déterminer l'ordre (jour, mois, année)
|
|
53
|
+
const formatParts = format.split(separator)
|
|
54
|
+
const dateParts = dateStr.split(separator)
|
|
55
|
+
|
|
56
|
+
// Si le nombre de parties ne correspond pas, retourner la chaîne originale
|
|
57
|
+
if (formatParts.length !== dateParts.length) {
|
|
58
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let day = -1
|
|
62
|
+
let month = -1
|
|
63
|
+
let year = -1
|
|
64
|
+
|
|
65
|
+
// Extraire les valeurs de jour, mois et année selon le format
|
|
66
|
+
for (let i = 0; i < formatParts.length; i++) {
|
|
67
|
+
const formatPart = formatParts[i].toUpperCase()
|
|
68
|
+
const value = parseInt(dateParts[i], 10)
|
|
69
|
+
|
|
70
|
+
if (isNaN(value)) {
|
|
71
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (formatPart.startsWith('D')) {
|
|
75
|
+
day = value
|
|
76
|
+
}
|
|
77
|
+
else if (formatPart.startsWith('M')) {
|
|
78
|
+
month = value - 1 // Convertir en index de mois (0-11)
|
|
79
|
+
}
|
|
80
|
+
else if (formatPart.startsWith('Y')) {
|
|
81
|
+
year = value
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Vérifier si toutes les parties nécessaires ont été trouvées
|
|
86
|
+
if (day === -1 || month === -1 || year === -1) {
|
|
87
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Vérifier si nous avons une date valide
|
|
91
|
+
if (month < 0 || month > 11 || year < 0 || day < 1) {
|
|
92
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Calculer directement le nombre de jours dans le mois
|
|
96
|
+
const daysInMonth = dayjs(new Date(year, month, 1)).daysInMonth()
|
|
97
|
+
|
|
98
|
+
// Ajuster le jour si nécessaire
|
|
99
|
+
let adjusted = false
|
|
100
|
+
let clampedDay = day
|
|
101
|
+
|
|
102
|
+
if (day > daysInMonth) {
|
|
103
|
+
clampedDay = daysInMonth
|
|
104
|
+
adjusted = true
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Si aucun ajustement n'a été fait, retourner la chaîne originale
|
|
108
|
+
if (!adjusted) {
|
|
109
|
+
return { clampedDate: dateStr, adjusted: false }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Reconstruire la chaîne de date avec le jour ajusté
|
|
113
|
+
const newDateParts = [...dateParts]
|
|
114
|
+
for (let i = 0; i < formatParts.length; i++) {
|
|
115
|
+
const formatPart = formatParts[i].toUpperCase()
|
|
116
|
+
if (formatPart.startsWith('D')) {
|
|
117
|
+
// Formater le jour avec le bon nombre de chiffres (01 ou 1 selon le format)
|
|
118
|
+
newDateParts[i] = formatPart.length > 1
|
|
119
|
+
? clampedDay.toString().padStart(2, '0')
|
|
120
|
+
: clampedDay.toString()
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
clampedDate: newDateParts.join(separator),
|
|
126
|
+
adjusted: true,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
autoClampDate,
|
|
132
|
+
clampDayToValidDate,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default useDateAutoClamp
|