@cnamts/synapse 0.0.12-alpha → 0.0.13-alpha

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.
Files changed (250) hide show
  1. package/dist/design-system-v3.js +4913 -4021
  2. package/dist/design-system-v3.umd.cjs +1 -1
  3. package/dist/src/components/Amelipro/types/types.d.ts +30 -57
  4. package/dist/src/components/Customs/SyTextField/SyTextField.d.ts +2 -0
  5. package/dist/src/components/DatePicker/DatePicker.d.ts +36 -44
  6. package/dist/src/components/DatePicker/DateTextInput.d.ts +33 -36
  7. package/dist/src/components/FilterInline/AccessibiliteItems.d.ts +30 -0
  8. package/dist/src/components/FilterInline/constants/ExpertiseLevelEnum.d.ts +4 -0
  9. package/dist/src/components/FilterSideBar/AccessibiliteItems.d.ts +29 -0
  10. package/dist/src/components/FilterSideBar/constants/ExpertiseLevelEnum.d.ts +4 -0
  11. package/dist/src/components/NirField/NirField.d.ts +14 -2
  12. package/dist/src/components/NotificationBar/NotificationBar.d.ts +5 -5
  13. package/dist/src/components/PasswordField/PasswordField.d.ts +2 -0
  14. package/dist/src/components/PeriodField/PeriodField.d.ts +159 -157
  15. package/dist/src/components/PhoneField/PhoneField.d.ts +22 -1
  16. package/dist/src/components/UploadWorkflow/AccessibiliteItems.d.ts +29 -0
  17. package/dist/src/components/UploadWorkflow/constants/ExpertiseLevelEnum.d.ts +4 -0
  18. package/dist/src/components/Usages/Usages.d.ts +10 -0
  19. package/dist/src/components/index.d.ts +3 -0
  20. package/dist/src/composables/date/tests/useDatePickerAccessibility.spec.d.ts +1 -0
  21. package/dist/src/composables/date/useDateFormat.d.ts +26 -0
  22. package/dist/src/composables/date/useDateInitialization.d.ts +18 -0
  23. package/dist/src/composables/date/useDatePickerAccessibility.d.ts +8 -0
  24. package/dist/src/composables/useFilterable/useFilterable.d.ts +1 -1
  25. package/dist/src/composables/validation/useValidation.d.ts +1 -0
  26. package/dist/src/main.d.ts +1 -0
  27. package/dist/src/utils/formatDate/index.d.ts +3 -0
  28. package/dist/src/utils/formatDate/tests/formatDate.spec.d.ts +1 -0
  29. package/dist/src/utils/functions/validation/isDateAfter/index.d.ts +2 -0
  30. package/dist/src/utils/functions/validation/isDateAfter/tests/isDateAfter.spec.d.ts +1 -0
  31. package/dist/src/utils/functions/validation/isDateBefore/index.d.ts +2 -0
  32. package/dist/src/utils/functions/validation/isDateBefore/tests/isDateBefore.spec.d.ts +1 -0
  33. package/dist/src/utils/functions/validation/isDateInRange/index.d.ts +3 -0
  34. package/dist/src/utils/functions/validation/isDateInRange/tests/isDateInRange.spec.d.ts +1 -0
  35. package/dist/src/utils/functions/validation/isDateValid/index.d.ts +9 -0
  36. package/dist/src/utils/functions/validation/isDateValid/tests/isDateValid.spec.d.ts +1 -0
  37. package/dist/src/utils/functions/validation/isEmailValid/tests/isEmailValid.spec.d.ts +1 -0
  38. package/dist/src/utils/functions/validation/isWeekend/index.d.ts +3 -0
  39. package/dist/src/utils/functions/validation/isWeekend/tests/isWeekend.spec.d.ts +1 -0
  40. package/dist/src/utils/parseDate/index.d.ts +3 -0
  41. package/dist/src/utils/parseDate/tests/parseDate.spec.d.ts +1 -0
  42. package/dist/src/utils/rules/doMatchPattern/index.d.ts +3 -0
  43. package/dist/src/utils/rules/doMatchPattern/tests/matchPattern.spec.d.ts +1 -0
  44. package/dist/src/utils/rules/index.d.ts +11 -0
  45. package/dist/src/utils/rules/isDateValid/index.d.ts +4 -0
  46. package/dist/src/utils/rules/isDateValid/tests/isDateValid.spec.d.ts +1 -0
  47. package/dist/src/utils/rules/isExactLength/index.d.ts +3 -0
  48. package/dist/src/utils/rules/isExactLength/locales.d.ts +2 -0
  49. package/dist/src/utils/rules/isExactLength/tests/exactLength.spec.d.ts +1 -0
  50. package/dist/src/utils/rules/isMaxLength/index.d.ts +3 -0
  51. package/dist/src/utils/rules/isMaxLength/locales.d.ts +2 -0
  52. package/dist/src/utils/rules/isMaxLength/tests/isMaxLength.spec.d.ts +1 -0
  53. package/dist/src/utils/rules/isMinLength/index.d.ts +3 -0
  54. package/dist/src/utils/rules/isMinLength/locales.d.ts +2 -0
  55. package/dist/src/utils/rules/isMinLength/tests/isMinLength.spec.d.ts +1 -0
  56. package/dist/src/utils/rules/isNotAfterDate/index.d.ts +3 -0
  57. package/dist/src/utils/rules/isNotAfterDate/tests/isNotAfterDate.spec.d.ts +1 -0
  58. package/dist/src/utils/rules/isNotAfterToday/index.d.ts +4 -0
  59. package/dist/src/utils/rules/isNotAfterToday/locales.d.ts +2 -0
  60. package/dist/src/utils/rules/isNotAfterToday/tests/isNotAfterToday.spec.d.ts +1 -0
  61. package/dist/src/utils/rules/isNotBeforeDate/index.d.ts +3 -0
  62. package/dist/src/utils/rules/isNotBeforeDate/locales.d.ts +2 -0
  63. package/dist/src/utils/rules/isNotBeforeDate/tests/IsNotBeforeDate.spec.d.ts +1 -0
  64. package/dist/src/utils/rules/isNotBeforeToday/index.d.ts +4 -0
  65. package/dist/src/utils/rules/isNotBeforeToday/locales.d.ts +2 -0
  66. package/dist/src/utils/rules/isNotBeforeToday/tests/notBeforeToday.spec.d.ts +1 -0
  67. package/dist/src/utils/rules/isRequired/index.d.ts +4 -0
  68. package/dist/src/utils/rules/isRequired/locales.d.ts +2 -0
  69. package/dist/src/utils/rules/isRequired/tests/isRequred.spec.d.ts +1 -0
  70. package/dist/src/utils/rules/isValidEmail/index.d.ts +4 -0
  71. package/dist/src/utils/rules/isValidEmail/locales.d.ts +2 -0
  72. package/dist/src/utils/rules/isValidEmail/tests/isValidEmail.spec.d.ts +1 -0
  73. package/dist/style.css +1 -1
  74. package/package.json +3 -1
  75. package/src/assets/_radius.scss +12 -6
  76. package/src/assets/settings.scss +8 -0
  77. package/src/components/Amelipro/types/types.ts +40 -0
  78. package/src/components/ChipList/ChipList.stories.ts +26 -27
  79. package/src/components/ChipList/ChipList.vue +5 -1
  80. package/src/components/ChipList/config.ts +1 -0
  81. package/src/components/CookiesSelection/CookiesInformation/CookiesInformation.vue +2 -2
  82. package/src/components/Customs/SyBtnSelect/SyBtnSelect.mdx +1 -1
  83. package/src/components/Customs/SyInputSelect/SyInputSelect.mdx +1 -1
  84. package/src/components/Customs/SySelect/SySelect.mdx +1 -1
  85. package/src/components/Customs/SySelect/SySelect.vue +19 -4
  86. package/src/components/Customs/SyTextField/SyTextField.mdx +2 -2
  87. package/src/components/Customs/SyTextField/SyTextField.stories.ts +239 -0
  88. package/src/components/Customs/SyTextField/SyTextField.vue +3 -0
  89. package/src/components/DatePicker/DatePicker.stories.ts +177 -5
  90. package/src/components/DatePicker/DatePicker.vue +148 -347
  91. package/src/components/DatePicker/DateTextInput.vue +91 -251
  92. package/src/components/DatePicker/tests/DatePicker.spec.ts +118 -48
  93. package/src/components/DatePicker/tests/DateTextInput.spec.ts +202 -6
  94. package/src/components/FileList/Accessibilite.stories.ts +1 -1
  95. package/src/components/FileList/AccessibiliteItems.ts +22 -0
  96. package/src/components/FileUpload/FileUpload.stories.ts +9 -7
  97. package/src/components/FilterInline/Accessibilite.mdx +14 -0
  98. package/src/components/FilterInline/Accessibilite.stories.ts +216 -0
  99. package/src/components/FilterInline/AccessibiliteItems.ts +132 -0
  100. package/src/components/FilterInline/constants/ExpertiseLevelEnum.ts +4 -0
  101. package/src/components/FilterSideBar/Accessibilite.mdx +14 -0
  102. package/src/components/FilterSideBar/Accessibilite.stories.ts +216 -0
  103. package/src/components/FilterSideBar/AccessibiliteItems.ts +153 -0
  104. package/src/components/FilterSideBar/constants/ExpertiseLevelEnum.ts +4 -0
  105. package/src/components/NirField/NirField.stories.ts +165 -0
  106. package/src/components/NirField/NirField.vue +6 -2
  107. package/src/components/NirField/tests/config.spec.ts +65 -0
  108. package/src/components/NotificationBar/NotificationBar.mdx +2 -2
  109. package/src/components/NotificationBar/NotificationBar.stories.ts +59 -11
  110. package/src/components/NotificationBar/NotificationBar.vue +42 -114
  111. package/src/components/NotificationBar/tests/NotificationBar.spec.ts +28 -33
  112. package/src/components/NotificationBar/tests/__snapshots__/NotificationBar.spec.ts.snap +1 -1
  113. package/src/components/PaginatedTable/PaginatedTable.vue +6 -10
  114. package/src/components/PaginatedTable/tests/__snapshots__/PaginatedTable.spec.ts.snap +4 -4
  115. package/src/components/PasswordField/PasswordField.stories.ts +191 -4
  116. package/src/components/PasswordField/PasswordField.vue +3 -0
  117. package/src/components/PeriodField/PeriodField.stories.ts +214 -118
  118. package/src/components/PeriodField/PeriodField.vue +195 -148
  119. package/src/components/PeriodField/tests/PeriodField.spec.ts +146 -0
  120. package/src/components/PhoneField/PhoneField.stories.ts +101 -0
  121. package/src/components/PhoneField/PhoneField.vue +73 -17
  122. package/src/components/PhoneField/tests/PhoneField.spec.ts +40 -0
  123. package/src/components/RatingPicker/RatingPicker.stories.ts +7 -7
  124. package/src/components/SearchListField/SearchListField.stories.ts +1 -1
  125. package/src/components/UploadWorkflow/Accessibilite.mdx +14 -0
  126. package/src/components/UploadWorkflow/Accessibilite.stories.ts +216 -0
  127. package/src/components/UploadWorkflow/AccessibiliteItems.ts +192 -0
  128. package/src/components/UploadWorkflow/UploadWorkflow.vue +2 -2
  129. package/src/components/UploadWorkflow/constants/ExpertiseLevelEnum.ts +4 -0
  130. package/src/components/Usages/tests/Usages.spec.ts +183 -0
  131. package/src/components/index.ts +3 -0
  132. package/src/composables/date/tests/useDateFormat.spec.ts +67 -0
  133. package/src/composables/date/tests/useDateInitialization.spec.ts +89 -0
  134. package/src/composables/date/tests/useDatePickerAccessibility.spec.ts +102 -0
  135. package/src/composables/date/useDateFormat.ts +94 -0
  136. package/src/composables/date/useDateInitialization.ts +92 -0
  137. package/src/composables/date/useDatePickerAccessibility.ts +78 -0
  138. package/src/composables/rules/tests/useFieldValidation.spec.ts +385 -4
  139. package/src/composables/useFilterable/useFilterable.ts +5 -4
  140. package/src/composables/validation/useValidation.ts +15 -0
  141. package/src/main.ts +1 -0
  142. package/src/stories/Accessibilite/Aculturation/AuditDesignSystem.mdx +28 -0
  143. package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +2 -2
  144. package/src/stories/Accessibilite/Audit/RGAA.mdx +6 -6
  145. package/src/stories/Accessibilite/Introduction.mdx +2 -1
  146. package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +1 -1
  147. package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +1 -1
  148. package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +8 -11
  149. package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +77 -0
  150. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru.mdx +9 -3
  151. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +2 -2
  152. package/src/stories/Demarrer/Introduction.stories.ts +3 -3
  153. package/src/stories/Demarrer/Releases.mdx +8 -0
  154. package/src/stories/Demarrer/Releases.stories.ts +66 -0
  155. package/src/stories/DesignTokens/Conteneurs.stories.ts +3 -3
  156. package/src/stories/GuideDuDev/LesBreackingChanges.mdx +36 -0
  157. package/src/stories/GuideDuDev/UtiliserLesRules.mdx +2 -2
  158. package/src/utils/formatDate/index.ts +6 -0
  159. package/src/utils/formatDate/tests/formatDate.spec.ts +18 -0
  160. package/src/utils/functions/validation/isDateAfter/index.ts +9 -0
  161. package/src/utils/functions/validation/isDateAfter/tests/isDateAfter.spec.ts +18 -0
  162. package/src/utils/functions/validation/isDateBefore/index.ts +9 -0
  163. package/src/utils/functions/validation/isDateBefore/tests/isDateBefore.spec.ts +23 -0
  164. package/src/utils/functions/validation/isDateInRange/index.ts +22 -0
  165. package/src/utils/functions/validation/isDateInRange/tests/isDateInRange.spec.ts +28 -0
  166. package/src/utils/functions/validation/isDateValid/index.ts +67 -0
  167. package/src/utils/functions/validation/isDateValid/tests/isDateValid.spec.ts +46 -0
  168. package/src/utils/functions/validation/isEmailValid/index.ts +9 -0
  169. package/src/utils/functions/validation/isWeekend/index.ts +10 -0
  170. package/src/utils/functions/validation/isWeekend/tests/isWeekend.spec.ts +16 -0
  171. package/src/utils/parseDate/index.ts +29 -0
  172. package/src/utils/parseDate/tests/parseDate.spec.ts +52 -0
  173. package/src/utils/rules/Rules.mdx +16 -0
  174. package/src/utils/rules/doMatchPattern/DoMachPattern.mdx +66 -0
  175. package/src/utils/rules/doMatchPattern/DoMatchPattern.stories.ts +106 -0
  176. package/src/utils/rules/doMatchPattern/index.ts +28 -0
  177. package/src/utils/rules/doMatchPattern/locales.ts +5 -0
  178. package/src/utils/rules/doMatchPattern/tests/matchPattern.spec.ts +38 -0
  179. package/src/utils/rules/index.ts +11 -0
  180. package/src/utils/rules/isDateValid/IsDateValid.mdx +87 -0
  181. package/src/utils/rules/isDateValid/IsDateValid.stories.ts +113 -0
  182. package/src/utils/rules/isDateValid/index.ts +32 -0
  183. package/src/utils/rules/isDateValid/locales.ts +10 -0
  184. package/src/utils/rules/isDateValid/tests/isDateValid.spec.ts +27 -0
  185. package/src/utils/rules/isExactLength/IsExactLenght.mdx +68 -0
  186. package/src/utils/rules/isExactLength/IsExactLength.stories.ts +151 -0
  187. package/src/utils/rules/{exactLength → isExactLength}/index.ts +2 -4
  188. package/src/utils/rules/isExactLength/tests/exactLength.spec.ts +48 -0
  189. package/src/utils/rules/isMaxLength/IsMaxLength.mdx +68 -0
  190. package/src/utils/rules/isMaxLength/IsMaxLength.stories.ts +152 -0
  191. package/src/utils/rules/isMaxLength/index.ts +30 -0
  192. package/src/utils/rules/isMaxLength/locales.ts +6 -0
  193. package/src/utils/rules/isMaxLength/tests/isMaxLength.spec.ts +42 -0
  194. package/src/utils/rules/isMinLength/IsMinLength.mdx +68 -0
  195. package/src/utils/rules/isMinLength/IsMinLength.stories.ts +152 -0
  196. package/src/utils/rules/isMinLength/index.ts +30 -0
  197. package/src/utils/rules/isMinLength/locales.ts +6 -0
  198. package/src/utils/rules/isMinLength/tests/isMinLength.spec.ts +42 -0
  199. package/src/utils/rules/isNotAfterDate/IsNotAfterDate.mdx +68 -0
  200. package/src/utils/rules/isNotAfterDate/IsNotAfterDate.stories.ts +109 -0
  201. package/src/utils/rules/isNotAfterDate/index.ts +25 -0
  202. package/src/utils/rules/isNotAfterDate/locales.ts +6 -0
  203. package/src/utils/rules/isNotAfterDate/tests/isNotAfterDate.spec.ts +25 -0
  204. package/src/utils/rules/isNotAfterToday/IsNotAfterToday.mdx +83 -0
  205. package/src/utils/rules/isNotAfterToday/IsNotAfterToday.stories.ts +110 -0
  206. package/src/utils/rules/isNotAfterToday/index.ts +28 -0
  207. package/src/utils/rules/isNotAfterToday/locales.ts +5 -0
  208. package/src/utils/rules/isNotAfterToday/tests/isNotAfterToday.spec.ts +30 -0
  209. package/src/utils/rules/isNotBeforeDate/IsNotBeforeDate.mdx +68 -0
  210. package/src/utils/rules/isNotBeforeDate/IsNotBeforeDate.stories.ts +114 -0
  211. package/src/utils/rules/isNotBeforeDate/index.ts +25 -0
  212. package/src/utils/rules/isNotBeforeDate/locales.ts +6 -0
  213. package/src/utils/rules/isNotBeforeDate/tests/IsNotBeforeDate.spec.ts +25 -0
  214. package/src/utils/rules/isNotBeforeToday/IsNotBeforeToday.mdx +83 -0
  215. package/src/utils/rules/isNotBeforeToday/IsNotBeforeToday.stories.ts +110 -0
  216. package/src/utils/rules/isNotBeforeToday/index.ts +28 -0
  217. package/src/utils/rules/isNotBeforeToday/locales.ts +5 -0
  218. package/src/utils/rules/isNotBeforeToday/tests/notBeforeToday.spec.ts +36 -0
  219. package/src/utils/rules/isRequired/IsRequired.mdx +81 -0
  220. package/src/utils/rules/isRequired/IsRequired.stories.ts +101 -0
  221. package/src/utils/rules/{required → isRequired}/index.ts +3 -3
  222. package/src/utils/rules/{required/tests/index.spec.ts → isRequired/tests/isRequred.spec.ts} +9 -9
  223. package/src/utils/rules/isValidEmail/IsValidEmail.mdx +81 -0
  224. package/src/utils/rules/isValidEmail/IsValidEmail.stories.ts +101 -0
  225. package/src/utils/rules/{email → isValidEmail}/index.ts +3 -5
  226. package/src/utils/rules/{email/tests/email.spec.ts → isValidEmail/tests/isValidEmail.spec.ts} +5 -5
  227. package/dist/src/components/Amelipro/types/languages.d.ts +0 -6
  228. package/dist/src/utils/rules/email/index.d.ts +0 -4
  229. package/dist/src/utils/rules/exactLength/index.d.ts +0 -4
  230. package/dist/src/utils/rules/required/index.d.ts +0 -4
  231. package/dist/src/utils/rules/required/ruleMessageHelper.d.ts +0 -3
  232. package/src/components/Amelipro/types/languages.d.ts +0 -6
  233. package/src/components/Amelipro/types/types.d.ts +0 -65
  234. package/src/components/Customs/SyTextField/tests/__snapshots__/SyTextField.spec.ts.snap +0 -58
  235. package/src/utils/functions/isEmailValid/index.ts +0 -8
  236. package/src/utils/rules/required/ruleMessageHelper.ts +0 -14
  237. package/src/utils/rules/required/tests/rulesMessageHelper.spec.ts +0 -22
  238. /package/dist/src/{utils/functions/isEmailValid/tests/isEmailValid.spec.d.ts → components/NirField/tests/config.spec.d.ts} +0 -0
  239. /package/dist/src/{utils/rules/email/tests/email.spec.d.ts → components/Usages/tests/Usages.spec.d.ts} +0 -0
  240. /package/dist/src/{utils/rules/required/tests/index.spec.d.ts → composables/date/tests/useDateFormat.spec.d.ts} +0 -0
  241. /package/dist/src/{utils/rules/required/tests/rulesMessageHelper.spec.d.ts → composables/date/tests/useDateInitialization.spec.d.ts} +0 -0
  242. /package/dist/src/utils/functions/{isEmailValid → validation/isEmailValid}/index.d.ts +0 -0
  243. /package/dist/src/utils/rules/{exactLength → doMatchPattern}/locales.d.ts +0 -0
  244. /package/dist/src/utils/rules/{email → isDateValid}/locales.d.ts +0 -0
  245. /package/dist/src/utils/rules/{required → isNotAfterDate}/locales.d.ts +0 -0
  246. /package/src/components/NirField/{tests → examples}//342/200/257dataset/342/200/257.md" +0 -0
  247. /package/src/utils/functions/{isEmailValid → validation/isEmailValid}/tests/isEmailValid.spec.ts +0 -0
  248. /package/src/utils/rules/{exactLength → isExactLength}/locales.ts +0 -0
  249. /package/src/utils/rules/{required → isRequired}/locales.ts +0 -0
  250. /package/src/utils/rules/{email → isValidEmail}/locales.ts +0 -0
@@ -1,7 +1,9 @@
1
1
  <script lang="ts" setup>
2
- import { ref, watch, computed } from 'vue'
2
+ /* eslint-disable @typescript-eslint/no-explicit-any -- Nécessaire pour gérer différents types d'entrée */
3
+ import { ref, watch, computed, onMounted } from 'vue'
3
4
  import DatePicker from '@/components/DatePicker/DatePicker.vue'
4
- import { type RuleOptions, useFieldValidation } from '@/composables'
5
+ import { useFieldValidation } from '@/composables'
6
+ import { useValidation, type ValidationRule } from '@/composables/validation/useValidation'
5
7
 
6
8
  const { parseDate } = useFieldValidation()
7
9
 
@@ -23,8 +25,9 @@
23
25
  noCalendar?: boolean
24
26
  isOutlined?: boolean
25
27
  showSuccessMessages?: boolean
26
- customRules?: { type: string, options: RuleOptions }[]
27
- customWarningRules?: { type: string, options: RuleOptions }[]
28
+ customRules?: ValidationRule[]
29
+ customWarningRules?: ValidationRule[]
30
+ disableErrorHandling?: boolean
28
31
  }>(), {
29
32
  modelValue: () => ({ from: null, to: null }),
30
33
  placeholderFrom: 'Début',
@@ -39,95 +42,40 @@
39
42
  noIcon: false,
40
43
  noCalendar: false,
41
44
  isOutlined: true,
42
- showSuccessMessages: false,
45
+ showSuccessMessages: true,
43
46
  customRules: () => [],
44
47
  customWarningRules: () => [],
48
+ disableErrorHandling: false,
45
49
  })
46
50
 
47
51
  const emit = defineEmits(['update:modelValue'])
48
52
 
53
+ // Références aux composants DatePicker
54
+ const fromDateRef = ref()
55
+ const toDateRef = ref()
56
+
57
+ // Valeurs internes pour les dates
49
58
  const internalFromDate = ref<string | null>(null)
50
59
  const internalToDate = ref<string | null>(null)
51
60
 
52
- // Règles de validation pour la date de début
53
- const fromDateRules = [
54
- {
55
- type: 'custom',
56
- options: {
57
- validate: (value: Date | null) => {
58
- if (value === null) return true
59
- if (tempToDate.value === undefined || tempToDate.value === null) return true
60
- return value <= tempToDate.value
61
- },
62
- message: 'La date de début ne peut pas être supérieure à la date de fin.',
63
- successMessage: 'La date de début est valide.',
64
- fieldIdentifier: 'fromDateRef',
65
- },
66
- },
67
- ...(props.required
68
- ? [{
69
- type: 'required',
70
- options: {
71
- validate: (value: Date | null) => {
72
- // Si les deux champs sont vides, on affiche l'erreur sur les deux
73
- if (!value && !tempToDate.value) {
74
- return false
75
- }
76
- // Si l'autre champ est rempli, on force la validation de celui-ci
77
- if (!value && tempToDate.value) {
78
- return false
79
- }
80
- return true
81
- },
82
- message: 'La date de début est requise.',
83
- successMessage: 'La date de début est renseignée.',
84
- fieldIdentifier: 'fromDateRef',
85
- },
86
- }]
87
- : []),
88
- ...props.customRules,
89
- ]
61
+ // Utiliser le composable de validation
62
+ const fromDateValidation = useValidation({
63
+ showSuccessMessages: props.showSuccessMessages,
64
+ fieldIdentifier: 'fromDate',
65
+ disableErrorHandling: props.disableErrorHandling,
66
+ })
90
67
 
91
- // Règles de validation pour la date de fin
92
- const toDateRules = [
93
- {
94
- type: 'custom',
95
- options: {
96
- validate: (value: Date | null) => {
97
- if (value === null) return true
98
- if (tempFromDate.value === undefined || tempFromDate.value === null) return true
99
- return value >= tempFromDate.value
100
- },
101
- message: 'La date de fin ne peut pas être inférieure à la date de début.',
102
- successMessage: 'La date de fin est valide.',
103
- fieldIdentifier: 'toDate',
104
- },
105
- },
106
- ...(props.required
107
- ? [{
108
- type: 'required',
109
- options: {
110
- validate: (value: Date | null) => {
111
- // Si les deux champs sont vides, on affiche l'erreur sur les deux
112
- if (!value && !tempFromDate.value) {
113
- return false
114
- }
115
- // Si l'autre champ est rempli, on force la validation de celui-ci
116
- if (!value && tempFromDate.value) {
117
- return false
118
- }
119
- return true
120
- },
121
- message: 'La date de fin est requise.',
122
- successMessage: 'La date de fin est renseignée.',
123
- fieldIdentifier: 'toDate',
124
- },
125
- }]
126
- : []),
127
- ...props.customRules,
128
- ]
68
+ const toDateValidation = useValidation({
69
+ showSuccessMessages: props.showSuccessMessages,
70
+ fieldIdentifier: 'toDate',
71
+ disableErrorHandling: props.disableErrorHandling,
72
+ })
129
73
 
130
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This is a generic type
74
+ /**
75
+ * Formate une valeur de date en chaîne de caractères au format spécifié
76
+ * @param value - La valeur de date à formater
77
+ * @returns La date formatée ou null
78
+ */
131
79
  function formatDateValue(value: any): string | null {
132
80
  if (!value) return null
133
81
  if (typeof value === 'string') return value
@@ -145,25 +93,102 @@
145
93
  const formattedFromDate = computed(() => formatDateValue(internalFromDate.value))
146
94
  const formattedToDate = computed(() => formatDateValue(internalToDate.value))
147
95
 
148
- // Computed properties pour les dates temporaires
149
- const tempFromDate = computed(() => formattedFromDate.value ? parseDate(formattedFromDate.value, props.format) : undefined)
150
- const tempToDate = computed(() => formattedToDate.value ? parseDate(formattedToDate.value, props.format) : undefined)
151
-
152
- // Sets pour optimiser la recherche des erreurs et succès
153
- const fromDateErrorsSet = computed(() => new Set(errors.value.filter(error => error.includes('fromDate'))))
154
- const toDateErrorsSet = computed(() => new Set(errors.value.filter(error => error.includes('toDate'))))
155
- const fromDateSuccessesSet = computed(() => new Set(successes.value.filter(success => success.includes('fromDate'))))
156
- const toDateSuccessesSet = computed(() => new Set(successes.value.filter(success => success.includes('toDate'))))
96
+ // Computed properties pour les dates parsées
97
+ const parsedFromDate = computed(() => formattedFromDate.value ? parseDate(formattedFromDate.value, props.format) : null)
98
+ const parsedToDate = computed(() => formattedToDate.value ? parseDate(formattedToDate.value, props.format) : null)
157
99
 
158
- const hasFromDateErrors = computed(() => fromDateErrorsSet.value.size > 0)
159
- const hasToDateErrors = computed(() => toDateErrorsSet.value.size > 0)
160
- const hasFromDateSuccesses = computed(() => fromDateSuccessesSet.value.size > 0)
161
- const hasToDateSuccesses = computed(() => toDateSuccessesSet.value.size > 0)
162
-
163
- const errors = ref<string[]>([])
164
- const successes = ref<string[]>([])
100
+ // Règles de validation pour la date de début
101
+ const fromDateRules = computed<ValidationRule[]>(() =>
102
+ !props.disableErrorHandling
103
+ ? [
104
+ {
105
+ type: 'custom',
106
+ options: {
107
+ validate: (value: Date | null) => {
108
+ if (value === null) return true
109
+ if (parsedToDate.value === null) return true
110
+ return value <= parsedToDate.value
111
+ },
112
+ message: 'La date de début ne peut pas être supérieure à la date de fin.',
113
+ successMessage: 'La date de début est valide.',
114
+ fieldIdentifier: 'fromDate',
115
+ },
116
+ },
117
+ ...(props.required && !props.disableErrorHandling
118
+ ? [{
119
+ type: 'required',
120
+ options: {
121
+ validate: (value: Date | null) => {
122
+ // Si les deux champs sont vides, on affiche l'erreur sur les deux
123
+ if (!value && !parsedToDate.value) {
124
+ return false
125
+ }
126
+ // Si l'autre champ est rempli, on force la validation de celui-ci
127
+ if (!value && parsedToDate.value) {
128
+ return false
129
+ }
130
+ return true
131
+ },
132
+ message: 'La date de début est requise.',
133
+ successMessage: 'La date de début est renseignée.',
134
+ fieldIdentifier: 'fromDate',
135
+ },
136
+ }]
137
+ : []),
138
+ ...(!props.disableErrorHandling ? props.customRules : []),
139
+ ]
140
+ : [],
141
+ )
142
+
143
+ // Variable réactive pour contrôler l'affichage des messages de succès
144
+ const showSuccessMessagesActual = computed(() =>
145
+ props.disableErrorHandling ? false : props.showSuccessMessages,
146
+ )
165
147
 
166
- // Computed property pour vérifier si le formulaire est valide
148
+ // Règles de validation pour la date de fin
149
+ const toDateRules = computed<ValidationRule[]>(() =>
150
+ !props.disableErrorHandling
151
+ ? [
152
+ {
153
+ type: 'custom',
154
+ options: {
155
+ validate: (value: Date | null) => {
156
+ if (value === null) return true
157
+ if (parsedFromDate.value === null) return true
158
+ return value >= parsedFromDate.value
159
+ },
160
+ message: 'La date de fin ne peut pas être inférieure à la date de début.',
161
+ successMessage: 'La date de fin est valide.',
162
+ fieldIdentifier: 'toDate',
163
+ },
164
+ },
165
+ ...(props.required
166
+ ? [{
167
+ type: 'required',
168
+ options: {
169
+ validate: (value: Date | null) => {
170
+ // Si les deux champs sont vides, on affiche l'erreur sur les deux
171
+ if (!value && !parsedFromDate.value) {
172
+ return false
173
+ }
174
+ // Si l'autre champ est rempli, on force la validation de celui-ci
175
+ if (!value && parsedFromDate.value) {
176
+ return false
177
+ }
178
+ return true
179
+ },
180
+ message: 'La date de fin est requise.',
181
+ successMessage: 'La date de fin est renseignée.',
182
+ fieldIdentifier: 'toDate',
183
+ },
184
+ }]
185
+ : []),
186
+ ...props.customRules,
187
+ ]
188
+ : [],
189
+ )
190
+
191
+ // Vérification de la validité du formulaire en utilisant les validations
167
192
  const isValid = computed(() => {
168
193
  // Si aucune date n'est renseignée et que ce n'est pas required, c'est valide
169
194
  if (!props.required && !formattedFromDate.value && !formattedToDate.value) {
@@ -184,35 +209,57 @@
184
209
  }
185
210
 
186
211
  // Si les deux dates sont renseignées, vérifier qu'elles sont cohérentes
187
- if (formattedFromDate.value && formattedToDate.value) {
188
- const fromDate = parseDate(formattedFromDate.value, props.format)
189
- const toDate = parseDate(formattedToDate.value, props.format)
190
- if (!fromDate || !toDate || fromDate > toDate) {
212
+ if (formattedFromDate.value && formattedToDate.value && parsedFromDate.value && parsedToDate.value) {
213
+ if (parsedFromDate.value > parsedToDate.value) {
191
214
  return false
192
215
  }
193
216
  }
194
217
 
195
- // Vérifier qu'il n'y a pas d'erreurs
196
- return errors.value.length === 0
218
+ // Vérifier que les deux validations ne signalent pas d'erreurs
219
+ return !fromDateValidation.hasError.value && !toDateValidation.hasError.value
197
220
  })
198
221
 
199
- // Watch pour les changements de la date de début
222
+ // Synchronisation lorsque l'une des dates change
223
+ function validateBothDates() {
224
+ if (fromDateRef.value) {
225
+ fromDateRef.value.validateOnSubmit()
226
+ }
227
+ if (toDateRef.value) {
228
+ toDateRef.value.validateOnSubmit()
229
+ }
230
+ }
231
+
232
+ // Validation complète du PeriodField
233
+ function validateFields() {
234
+ fromDateValidation.validateField(parsedFromDate.value, fromDateRules.value, props.customWarningRules)
235
+ toDateValidation.validateField(parsedToDate.value, toDateRules.value, props.customWarningRules)
236
+ }
237
+
238
+ // Gestionnaires d'événements closed
239
+ function handleFromDateClosed() {
240
+ validateBothDates()
241
+ }
242
+
243
+ function handleToDateClosed() {
244
+ validateBothDates()
245
+ }
246
+
247
+ // Watch pour les changements des dates - validation croisée
200
248
  watch(formattedFromDate, () => {
201
- // Si la date de fin existe, on revalide
249
+ validateFields()
202
250
  if (formattedToDate.value && toDateRef.value) {
203
251
  toDateRef.value.validateOnSubmit()
204
252
  }
205
253
  })
206
254
 
207
- // Watch pour les changements de la date de fin
208
255
  watch(formattedToDate, () => {
209
- // Si la date de début existe, on revalide
256
+ validateFields()
210
257
  if (formattedFromDate.value && fromDateRef.value) {
211
258
  fromDateRef.value.validateOnSubmit()
212
259
  }
213
260
  })
214
261
 
215
- // Watch pour les changements internes
262
+ // Watch pour les changements internes - Mise à jour du modèle
216
263
  watch([internalFromDate, internalToDate], () => {
217
264
  emit('update:modelValue', {
218
265
  from: formattedFromDate.value,
@@ -220,7 +267,7 @@
220
267
  })
221
268
  })
222
269
 
223
- // Watch pour les changements externes avec immediate pour synchroniser l'état initial
270
+ // Watch pour les changements externes - Synchronisation
224
271
  watch(() => props.modelValue, (newValue) => {
225
272
  if (!newValue) return
226
273
 
@@ -233,52 +280,52 @@
233
280
  if (internalToDate.value !== newToDate) {
234
281
  internalToDate.value = newToDate
235
282
  }
283
+ // Valider les champs après la mise à jour des valeurs
284
+ validateFields()
236
285
  }, { deep: true, immediate: true })
237
286
 
238
- // Initialisation
239
- internalFromDate.value = formatDateValue(props.modelValue?.from)
240
- internalToDate.value = formatDateValue(props.modelValue?.to)
241
-
242
- const fromDateRef = ref()
243
- const toDateRef = ref()
244
-
245
- // Gestionnaires d'événements closed
246
- const handleFromDateClosed = () => {
247
- if (fromDateRef.value) {
248
- fromDateRef.value.validateOnSubmit()
249
- }
250
- }
251
-
252
- const handleToDateClosed = () => {
253
- if (toDateRef.value) {
254
- toDateRef.value.validateOnSubmit()
255
- }
256
- }
257
-
287
+ // Fonction publique de validation
258
288
  const validateOnSubmit = (): boolean => {
259
289
  // Valider les deux DatePicker
260
290
  const fromDateValid = fromDateRef.value?.validateOnSubmit() ?? true
261
291
  const toDateValid = toDateRef.value?.validateOnSubmit() ?? true
262
292
 
263
- // Retourner true seulement si tout est valide
264
- const result = fromDateValid && toDateValid && isValid.value
293
+ // Valider avec les règles personnalisées
294
+ validateFields()
265
295
 
266
- return result
296
+ // Retourner true seulement si tout est valide
297
+ return fromDateValid && toDateValid && isValid.value
267
298
  }
268
299
 
300
+ // Initialisation
301
+ onMounted(() => {
302
+ internalFromDate.value = formatDateValue(props.modelValue?.from)
303
+ internalToDate.value = formatDateValue(props.modelValue?.to)
304
+ // Validation initiale
305
+ validateFields()
306
+ })
307
+
269
308
  defineExpose({
270
309
  validateOnSubmit,
271
- errors,
272
- successes,
310
+ errors: {
311
+ fromDate: fromDateValidation.errors,
312
+ toDate: toDateValidation.errors,
313
+ },
314
+ successes: {
315
+ fromDate: fromDateValidation.successes,
316
+ toDate: toDateValidation.successes,
317
+ },
318
+ warnings: {
319
+ fromDate: fromDateValidation.warnings,
320
+ toDate: toDateValidation.warnings,
321
+ },
273
322
  isValid,
274
323
  })
275
324
  </script>
276
325
 
277
326
  <template>
278
327
  <div class="period-field">
279
- <div
280
- class="period-field__col"
281
- >
328
+ <div class="period-field__col">
282
329
  <DatePicker
283
330
  ref="fromDateRef"
284
331
  v-model="internalFromDate"
@@ -287,22 +334,21 @@
287
334
  :date-format-return="props.dateFormatReturn"
288
335
  :display-append-icon="props.displayAppendIcon"
289
336
  :display-icon="props.displayIcon"
290
- :error-message="hasFromDateErrors"
337
+ :error-message="fromDateValidation.hasError"
291
338
  :format="props.format"
292
339
  :is-disabled="props.isDisabled"
293
340
  :is-outlined="props.isOutlined"
294
341
  :no-calendar="props.noCalendar"
295
342
  :no-icon="props.noIcon"
296
343
  :placeholder="props.placeholderFrom"
297
- :required="props.required"
344
+ :required="props.disableErrorHandling ? false : props.required"
298
345
  :show-week-number="props.showWeekNumber"
299
- :success-message="hasFromDateSuccesses"
346
+ :show-success-messages="showSuccessMessagesActual"
347
+ :success-message="fromDateValidation.hasSuccess"
300
348
  @closed="handleFromDateClosed"
301
349
  />
302
350
  </div>
303
- <div
304
- class="period-field__col"
305
- >
351
+ <div class="period-field__col">
306
352
  <DatePicker
307
353
  ref="toDateRef"
308
354
  v-model="internalToDate"
@@ -311,16 +357,17 @@
311
357
  :date-format-return="props.dateFormatReturn"
312
358
  :display-append-icon="props.displayAppendIcon"
313
359
  :display-icon="props.displayIcon"
314
- :error-message="hasToDateErrors"
360
+ :error-message="toDateValidation.hasError"
315
361
  :format="props.format"
316
362
  :is-disabled="props.isDisabled"
317
363
  :is-outlined="props.isOutlined"
318
364
  :no-calendar="props.noCalendar"
319
365
  :no-icon="props.noIcon"
320
366
  :placeholder="props.placeholderTo"
321
- :required="props.required"
367
+ :required="props.disableErrorHandling ? false : props.required"
322
368
  :show-week-number="props.showWeekNumber"
323
- :success-message="hasToDateSuccesses"
369
+ :show-success-messages="showSuccessMessagesActual"
370
+ :success-message="toDateValidation.hasSuccess"
324
371
  @closed="handleToDateClosed"
325
372
  />
326
373
  </div>
@@ -254,6 +254,152 @@ describe('PeriodField.vue', () => {
254
254
  await wrapper.vm.$nextTick()
255
255
  expect(wrapper.vm.isValid).toBe(true)
256
256
  })
257
+
258
+ it('validates correctly the required rule when fields are empty or partially filled', async () => {
259
+ // Cas 1: Tester la validation quand les deux champs sont vides
260
+ const wrapper1 = mount(PeriodField, {
261
+ global: {
262
+ plugins: [vuetify],
263
+ },
264
+ props: {
265
+ required: true,
266
+ modelValue: {
267
+ from: null,
268
+ to: null,
269
+ },
270
+ },
271
+ })
272
+
273
+ await wrapper1.vm.validateOnSubmit()
274
+ await wrapper1.vm.$nextTick()
275
+
276
+ // Vérifier que la fonction de validation renvoie false quand les deux champs sont vides
277
+ const fromDatePicker1 = wrapper1.findAllComponents({ name: 'DatePicker' })[0]
278
+ const requiredRule1 = fromDatePicker1.props('customRules').find(rule => rule.type === 'required')
279
+ expect(requiredRule1.options.validate(null)).toBe(false)
280
+ expect(wrapper1.vm.isValid).toBe(false)
281
+
282
+ // Cas 2: Tester la validation quand un champ est rempli mais l'autre est vide
283
+ const wrapper2 = mount(PeriodField, {
284
+ global: {
285
+ plugins: [vuetify],
286
+ },
287
+ props: {
288
+ required: true,
289
+ modelValue: {
290
+ from: null,
291
+ to: '20/12/2023',
292
+ },
293
+ },
294
+ })
295
+
296
+ await wrapper2.vm.validateOnSubmit()
297
+ await wrapper2.vm.$nextTick()
298
+
299
+ // Vérifier que la fonction de validation renvoie false quand from est vide mais to est rempli
300
+ const fromDatePicker2 = wrapper2.findAllComponents({ name: 'DatePicker' })[0]
301
+ const requiredRule2 = fromDatePicker2.props('customRules').find(rule => rule.type === 'required')
302
+ // Simuler le scénario où parsedToDate.value est non-null
303
+ expect(requiredRule2.options.validate(null)).toBe(false)
304
+ expect(wrapper2.vm.isValid).toBe(false)
305
+
306
+ // Cas 3: Tester que la validation renvoie true quand le champ n'est pas vide
307
+ const wrapper3 = mount(PeriodField, {
308
+ global: {
309
+ plugins: [vuetify],
310
+ },
311
+ props: {
312
+ required: true,
313
+ modelValue: {
314
+ from: '15/12/2023',
315
+ to: '20/12/2023',
316
+ },
317
+ },
318
+ })
319
+
320
+ await wrapper3.vm.validateOnSubmit()
321
+ await wrapper3.vm.$nextTick()
322
+
323
+ // Vérifier que la fonction de validation renvoie true quand le champ a une valeur
324
+ const fromDatePicker3 = wrapper3.findAllComponents({ name: 'DatePicker' })[0]
325
+ const requiredRule3 = fromDatePicker3.props('customRules').find(rule => rule.type === 'required')
326
+ const mockDate = new Date('2023-12-15')
327
+ expect(requiredRule3.options.validate(mockDate)).toBe(true)
328
+ expect(wrapper3.vm.isValid).toBe(true)
329
+ })
330
+
331
+ it('validates correctly the to-date required rule when fields are empty or partially filled', async () => {
332
+ // Cas 1: Tester la validation quand les deux champs sont vides
333
+ const wrapper1 = mount(PeriodField, {
334
+ global: {
335
+ plugins: [vuetify],
336
+ },
337
+ props: {
338
+ required: true,
339
+ modelValue: {
340
+ from: null,
341
+ to: null,
342
+ },
343
+ },
344
+ })
345
+
346
+ await wrapper1.vm.validateOnSubmit()
347
+ await wrapper1.vm.$nextTick()
348
+
349
+ // Vérifier que la fonction de validation renvoie false quand les deux champs sont vides
350
+ const toDatePicker1 = wrapper1.findAllComponents({ name: 'DatePicker' })[1]
351
+ const requiredRule1 = toDatePicker1.props('customRules').find(rule => rule.type === 'required')
352
+ expect(requiredRule1.options.validate(null)).toBe(false)
353
+ expect(wrapper1.vm.isValid).toBe(false)
354
+
355
+ // Cas 2: Tester la validation quand un champ est rempli mais l'autre est vide
356
+ const wrapper2 = mount(PeriodField, {
357
+ global: {
358
+ plugins: [vuetify],
359
+ },
360
+ props: {
361
+ required: true,
362
+ modelValue: {
363
+ from: '15/12/2023',
364
+ to: null,
365
+ },
366
+ },
367
+ })
368
+
369
+ await wrapper2.vm.validateOnSubmit()
370
+ await wrapper2.vm.$nextTick()
371
+
372
+ // Vérifier que la fonction de validation renvoie false quand to est vide mais from est rempli
373
+ const toDatePicker2 = wrapper2.findAllComponents({ name: 'DatePicker' })[1]
374
+ const requiredRule2 = toDatePicker2.props('customRules').find(rule => rule.type === 'required')
375
+ // Simuler le scénario où parsedFromDate.value est non-null
376
+ expect(requiredRule2.options.validate(null)).toBe(false)
377
+ expect(wrapper2.vm.isValid).toBe(false)
378
+
379
+ // Cas 3: Tester que la validation renvoie true quand le champ n'est pas vide
380
+ const wrapper3 = mount(PeriodField, {
381
+ global: {
382
+ plugins: [vuetify],
383
+ },
384
+ props: {
385
+ required: true,
386
+ modelValue: {
387
+ from: '15/12/2023',
388
+ to: '20/12/2023',
389
+ },
390
+ },
391
+ })
392
+
393
+ await wrapper3.vm.validateOnSubmit()
394
+ await wrapper3.vm.$nextTick()
395
+
396
+ // Vérifier que la fonction de validation renvoie true quand le champ a une valeur
397
+ const toDatePicker3 = wrapper3.findAllComponents({ name: 'DatePicker' })[1]
398
+ const requiredRule3 = toDatePicker3.props('customRules').find(rule => rule.type === 'required')
399
+ const mockDate = new Date('2023-12-20')
400
+ expect(requiredRule3.options.validate(mockDate)).toBe(true)
401
+ expect(wrapper3.vm.isValid).toBe(true)
402
+ })
257
403
  })
258
404
 
259
405
  describe('Utils', () => {