codevdesign 1.0.77 → 1.0.79

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 (94) hide show
  1. package/assets/csqc.css +28 -30
  2. package/composants/csqcAide.vue +1 -1
  3. package/composants/csqcAlerteErreur.vue +1 -1
  4. package/composants/csqcChaise/chaiseConteneur.vue +3 -3
  5. package/composants/csqcChaise/chaiseItem.vue +54 -54
  6. package/composants/csqcCodeBudgetaireGenerique.vue +254 -254
  7. package/composants/csqcConfirmation.vue +2 -1
  8. package/composants/csqcDate.vue +4 -1
  9. package/composants/csqcDialogue.vue +6 -4
  10. package/composants/csqcEditeurTexteRiche.vue +1 -1
  11. package/composants/csqcEntete.vue +17 -17
  12. package/composants/csqcImportCSV.vue +2 -2
  13. package/composants/csqcModaleSaisie.vue +1 -1
  14. package/composants/csqcRecherche.vue +7 -7
  15. package/composants/csqcRechercheUtilisateur.vue +1 -1
  16. package/composants/csqcSnackbar.vue +1 -1
  17. package/composants/csqcSwitch.vue +5 -5
  18. package/composants/csqcTable/csqcTable.vue +19 -14
  19. package/composants/csqcTable/csqcTableModaleChoixColonnes.vue +4 -4
  20. package/composants/csqcTable/sortableDataTable.ts +1 -1
  21. package/composants/csqcTexteBilingue.vue +175 -175
  22. package/composants/csqcTiroir.vue +7 -5
  23. package/composants/gabarit/csqcMenu.vue +4 -4
  24. package/composants/gabarit/pivEntete.vue +5 -3
  25. package/composants/gabarit/pivPiedPage.vue +44 -29
  26. package/composants/validateurs.ts +8 -2
  27. package/editeur.ts +1 -1
  28. package/importCSV.ts +1 -1
  29. package/index.ts +80 -80
  30. package/locales/en.json +1 -1
  31. package/locales/fr.json +3 -3
  32. package/modeles/assurancesAssuranceGeneraleGrics.ts +3 -3
  33. package/modeles/assurancesAssurancePersonnelleGrics.ts +6 -6
  34. package/modeles/assurancesContratGrics.ts +6 -6
  35. package/modeles/assurancesDetailsPrimeReguliereGrics.ts +4 -4
  36. package/modeles/assurancesDonneesAssureurGrics.ts +5 -5
  37. package/modeles/assurancesEmployeGrics.ts +4 -4
  38. package/modeles/assurancesGrics.ts +6 -6
  39. package/modeles/assurancesRegimeAssuranceGrics.ts +2 -2
  40. package/modeles/assurancesRegimeBaseEmployeurGrics.ts +2 -2
  41. package/modeles/assurancesRegimeBaseGrics.ts +2 -2
  42. package/modeles/composants/csqcMenuModele.ts +18 -18
  43. package/modeles/composants/datatableColonne.ts +19 -19
  44. package/modeles/employeAdresseGrics.ts +6 -6
  45. package/modeles/employeAdressesPersonnellesGrics.ts +4 -4
  46. package/modeles/employeAffectationCorpsEmploiGrics.ts +2 -2
  47. package/modeles/employeBanquesCongeBanqueGrics.ts +2 -2
  48. package/modeles/employeBanquesCongeGrics.ts +6 -6
  49. package/modeles/employeBanquesCongeRegimeAbsenceGrics.ts +2 -2
  50. package/modeles/employeCourrielsPersonnels.ts +2 -2
  51. package/modeles/employeCourrielsProfessionnels.ts +2 -2
  52. package/modeles/employeEmploisCategorieGrics.ts +2 -2
  53. package/modeles/employeEmploisClasseGrics.ts +2 -2
  54. package/modeles/employeEmploisCorpsEmploiGrics.ts +2 -2
  55. package/modeles/employeEmploisEtatEmploiGrics.ts +2 -2
  56. package/modeles/employeEmploisGrics.ts +29 -29
  57. package/modeles/employeEmploisGroupePaieGrics.ts +2 -2
  58. package/modeles/employeEmploisLieuTravailPrincipalGrics.ts +3 -3
  59. package/modeles/employeEmploisLieuxTravailSecondairesGrics.ts +3 -3
  60. package/modeles/employeEmploisRegimeAbsenceGrics.ts +2 -2
  61. package/modeles/employeEmploisSecteurGrics.ts +2 -2
  62. package/modeles/employeEmploisStatutEngagementGrics.ts +2 -2
  63. package/modeles/employeExperienceEmploiGrics.ts +2 -2
  64. package/modeles/employeExperienceEmployeGrics.ts +5 -5
  65. package/modeles/employeExperienceExperiencesGrics.ts +4 -4
  66. package/modeles/employeExperienceExperiencesTotalesGrics.ts +7 -7
  67. package/modeles/employeExperienceGrics.ts +9 -9
  68. package/modeles/employeGrics.ts +23 -23
  69. package/modeles/employeTelephoneGrics.ts +4 -4
  70. package/modeles/employeTelephonesPersonnelsGrics.ts +3 -3
  71. package/modeles/employeTelephonesProfessionnelsGrics.ts +3 -3
  72. package/modeles/groupeCE.ts +6 -6
  73. package/modeles/groupeCEIntervalle.ts +6 -6
  74. package/modeles/historiquesAbsenceBanqueGrics.ts +2 -2
  75. package/modeles/historiquesAbsenceGrics.ts +13 -13
  76. package/modeles/historiquesAbsenceLieuTravailGrics.ts +2 -2
  77. package/modeles/historiquesAbsenceSousBanqueGrics.ts +2 -2
  78. package/modeles/motifsAbsenceBanque.ts +2 -2
  79. package/modeles/motifsAbsenceGrics.ts +9 -9
  80. package/modeles/motifsAbsenceRegimeAbsence.ts +2 -2
  81. package/modeles/motifsAbsenceSousMotifs.ts +2 -2
  82. package/modeles/motifsAbsenceTraitementBanques.ts +3 -3
  83. package/modeles/syndicat.ts +18 -18
  84. package/modeles/syndicatGroupeCe.ts +3 -3
  85. package/modeles/syndicatResponsable.ts +8 -8
  86. package/modeles/syndicatUnite.ts +3 -3
  87. package/modeles/unite.ts +15 -15
  88. package/modeles/uniteTypeEnseignement.ts +4 -4
  89. package/modeles/utilisateur.ts +8 -8
  90. package/outils/appAxios.ts +16 -16
  91. package/outils/csqcOutils.ts +6 -5
  92. package/outils/csqcRafraichisseurTokenParent.ts +20 -4
  93. package/outils/rafraichisseurToken.ts +310 -310
  94. package/package.json +1 -1
@@ -21,7 +21,7 @@
21
21
  @blur="sauvegarder"
22
22
  @keydown.enter="sauvegarder"
23
23
  @keydown="caractereAutorises"
24
- @update:modelValue="gererChangement"
24
+ @update:model-value="gererChangement"
25
25
  @paste="gererPaste"
26
26
  >
27
27
  <template #item="{ props, item }">
@@ -37,294 +37,294 @@
37
37
  </template>
38
38
 
39
39
  <script setup lang="ts">
40
- import { ref, computed, onMounted, nextTick, watch } from 'vue'
41
- import type { VForm } from 'vuetify/components'
42
-
43
- const emit = defineEmits<{
44
- 'update:modelValue': [string | null]
45
- 'update:codeBudgetairesProp': [CodeBudgetaireItem[]]
46
- 'update:valide': [boolean]
47
- }>()
48
- type CodeBudgetaireItem = string | [string, string]
49
-
50
- const props = withDefaults(
51
- defineProps<{
52
- codeBudgetairesProp: CodeBudgetaireItem[]
53
- modelValue: string | null
54
- afficherHint?: boolean
55
- regleMessageErreur: string
56
- format?: string
57
- activerExtension?: boolean
58
- reglesSupp?: ((v: string) => true | string)[]
59
- }>(),
60
- {
61
- afficherHint: false,
62
- format: '999-9-99999-999',
63
- activerExtension: false,
64
- reglesSupp: () => [],
65
- },
66
- )
67
-
68
- const formValide = ref(false)
69
- const form = ref<VForm | null>(null)
70
- const codeBudgetaire = ref(props.modelValue ?? '')
71
- const derniereValeurSauvegardee = ref<string | null>(null)
72
- const format = props.format
73
- const activerExtension = props.activerExtension
74
-
75
- onMounted(() => {
76
- derniereValeurSauvegardee.value = codeBudgetaire.value
77
- })
78
-
79
- const itemsCombobox = computed(() => {
80
- return props.codeBudgetairesProp.map(item => {
81
- if (typeof item === 'string') {
82
- return {
83
- code: item,
84
- nom: '', // pas de nom
85
- }
86
- }
87
-
88
- const [code, nomBrut] = item
89
- const nom = (nomBrut ?? '').toString().trim()
90
-
91
- return { code, nom }
92
- })
93
- })
94
-
95
- const placeholder = computed(() => {
96
- const base = format.replace(/9/g, '0')
97
- const extension = activerExtension ? '-XXX/XXX' : ''
98
- return base + extension
99
- })
100
-
101
- const estValide = computed(() => {
102
- const val = codeBudgetaire.value?.toUpperCase().trim() || ''
103
- const base = val.slice(0, 15)
104
- const extension = val.slice(15)
105
-
106
- if (!/^\d{3}-\d{1}-\d{5}-\d{3}$/.test(base)) return false
107
-
108
- if (!activerExtension) return val.length === 15
109
-
110
- if (val.length === 15) return true
111
- if (val.length !== 22) return false
112
- if (extension.length !== 7) return false
113
-
114
- if (extension[3] !== '/') return false
115
- if (!/^[A-Z0-9/]$/i.test(extension[0]!)) return false
116
-
117
- const alphanumAt = [1, 2, 4, 5, 6]
118
- return alphanumAt.every(i => /^[A-Z0-9]$/i.test(extension[i]!))
119
- })
40
+ import { ref, computed, onMounted, nextTick, watch } from 'vue'
41
+ import type { VForm } from 'vuetify/components'
42
+
43
+ const emit = defineEmits<{
44
+ 'update:modelValue': [string | null]
45
+ 'update:codeBudgetairesProp': [CodeBudgetaireItem[]]
46
+ 'update:valide': [boolean]
47
+ }>()
48
+ type CodeBudgetaireItem = string | [string, string]
49
+
50
+ const props = withDefaults(
51
+ defineProps<{
52
+ codeBudgetairesProp: CodeBudgetaireItem[]
53
+ modelValue: string | null
54
+ afficherHint?: boolean
55
+ regleMessageErreur: string
56
+ format?: string
57
+ activerExtension?: boolean
58
+ reglesSupp?: ((v: string) => true | string)[]
59
+ }>(),
60
+ {
61
+ afficherHint: false,
62
+ format: '999-9-99999-999',
63
+ activerExtension: false,
64
+ reglesSupp: () => [],
65
+ },
66
+ )
120
67
 
121
- // Règles Vuetify combinées (interne + supplémentaires)
122
- const reglesVuetify = computed(() => [
123
- // règle interne
124
- () => (estValide.value ? true : props.regleMessageErreur),
125
-
126
- // règles supplémentaires venant du parent
127
- ...props.reglesSupp.map(rule => {
128
- return () => rule(codeBudgetaire.value) // on passe la valeur formatée
129
- }),
130
- ])
131
-
132
- // Validité globale du composant (interne + toutes les règles supp)
133
- const estValideComplet = computed(() => {
134
- if (!estValide.value) return false
135
- return props.reglesSupp.every(rule => rule(codeBudgetaire.value) === true)
136
- })
68
+ const formValide = ref(false)
69
+ const form = ref<VForm | null>(null)
70
+ const codeBudgetaire = ref(props.modelValue ?? '')
71
+ const derniereValeurSauvegardee = ref<string | null>(null)
72
+ const format = props.format
73
+ const activerExtension = props.activerExtension
74
+
75
+ onMounted(() => {
76
+ derniereValeurSauvegardee.value = codeBudgetaire.value
77
+ })
78
+
79
+ const itemsCombobox = computed(() => {
80
+ return props.codeBudgetairesProp.map(item => {
81
+ if (typeof item === 'string') {
82
+ return {
83
+ code: item,
84
+ nom: '', // pas de nom
85
+ }
86
+ }
137
87
 
138
- const caractereAutorises = (e: KeyboardEvent) => {
139
- if (e.ctrlKey || e.metaKey) return
88
+ const [code, nomBrut] = item
89
+ const nom = (nomBrut ?? '').toString().trim()
140
90
 
141
- const touchesSpecifiques = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End']
142
- if (touchesSpecifiques.includes(e.key)) return
91
+ return { code, nom }
92
+ })
93
+ })
143
94
 
144
- const input = e.target as HTMLInputElement
145
- let position = input.selectionStart ?? 0
95
+ const placeholder = computed(() => {
96
+ const base = format.replace(/9/g, '0')
97
+ const extension = activerExtension ? '-XXX/XXX' : ''
98
+ return base + extension
99
+ })
146
100
 
147
- // Gestion de la partie de base (15 premiers caractères)
148
- if (position < 15) {
149
- if (!/^\d$/.test(e.key)) {
150
- e.preventDefault()
151
- return
152
- }
101
+ const estValide = computed(() => {
102
+ const val = codeBudgetaire.value?.toUpperCase().trim() || ''
103
+ const base = val.slice(0, 15)
104
+ const extension = val.slice(15)
153
105
 
154
- // Insérer chiffre et auto-ajout des tirets
155
- e.preventDefault()
106
+ if (!/^\d{3}-\d{1}-\d{5}-\d{3}$/.test(base)) return false
156
107
 
157
- const value = codeBudgetaire.value.replace(/-/g, '')
158
- const clean = value.slice(0, 12) + e.key
108
+ if (!activerExtension) return val.length === 15
159
109
 
160
- let formatted = ''
161
- if (clean.length > 0) formatted += clean.slice(0, 3)
162
- if (clean.length > 3) formatted += '-' + clean.slice(3, 4)
163
- if (clean.length > 4) formatted += '-' + clean.slice(4, 9)
164
- if (clean.length > 9) formatted += '-' + clean.slice(9, 12)
110
+ if (val.length === 15) return true
111
+ if (val.length !== 22) return false
112
+ if (extension.length !== 7) return false
165
113
 
166
- codeBudgetaire.value = formatted.slice(0, 15)
114
+ if (extension[3] !== '/') return false
115
+ if (!/^[A-Z0-9/]$/i.test(extension[0]!)) return false
167
116
 
168
- nextTick(() => {
169
- const newPos = codeBudgetaire.value.length
170
- input.selectionStart = input.selectionEnd = newPos
171
- })
117
+ const alphanumAt = [1, 2, 4, 5, 6]
118
+ return alphanumAt.every(i => /^[A-Z0-9]$/i.test(extension[i]!))
119
+ })
172
120
 
173
- return
174
- }
121
+ // Règles Vuetify combinées (interne + supplémentaires)
122
+ const reglesVuetify = computed(() => [
123
+ // règle interne
124
+ () => (estValide.value ? true : props.regleMessageErreur),
175
125
 
176
- // --- Gestion de l'extension ---
177
- if (!activerExtension || position >= 22 || codeBudgetaire.value.length >= 22) {
178
- e.preventDefault()
179
- return
180
- }
126
+ // règles supplémentaires venant du parent
127
+ ...props.reglesSupp.map(rule => {
128
+ return () => rule(codeBudgetaire.value) // on passe la valeur formatée
129
+ }),
130
+ ])
181
131
 
182
- const extensionPos = position - 15
132
+ // Validité globale du composant (interne + toutes les règles supp)
133
+ const estValideComplet = computed(() => {
134
+ if (!estValide.value) return false
135
+ return props.reglesSupp.every(rule => rule(codeBudgetaire.value) === true)
136
+ })
183
137
 
184
- // Règle 1 : extension[0] = alphanum ou /
185
- if (extensionPos === 0) {
186
- if (!/^[A-Z0-9/]$/i.test(e.key)) {
187
- e.preventDefault()
188
- return
189
- }
190
- return
191
- }
138
+ const caractereAutorises = (e: KeyboardEvent) => {
139
+ if (e.ctrlKey || e.metaKey) return
192
140
 
193
- // Règle 2 : extension[1,2,4,5,6] = alphanum
194
- if ([1, 2, 4, 5, 6].includes(extensionPos)) {
195
- if (!/^[A-Z0-9]$/i.test(e.key)) {
196
- e.preventDefault()
197
- return
198
- }
199
- return
200
- }
141
+ const touchesSpecifiques = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End']
142
+ if (touchesSpecifiques.includes(e.key)) return
201
143
 
202
- // Règle 3 : slash automatique à position 3 (index 18)
203
- if (extensionPos === 3) {
204
- e.preventDefault()
205
- const before = codeBudgetaire.value.slice(0, position)
206
- const after = codeBudgetaire.value.slice(position)
207
- codeBudgetaire.value = before + '/' + after
208
- nextTick(() => {
209
- input.selectionStart = input.selectionEnd = position + 1
210
- })
211
- return
212
- }
144
+ const input = e.target as HTMLInputElement
145
+ const position = input.selectionStart ?? 0
213
146
 
214
- // Tout autre cas = bloqué
147
+ // Gestion de la partie de base (15 premiers caractères)
148
+ if (position < 15) {
149
+ if (!/^\d$/.test(e.key)) {
215
150
  e.preventDefault()
151
+ return
216
152
  }
217
153
 
218
- const formaterCodeBudgetaire = (valeur: string): string => {
219
- if (!valeur) return ''
220
-
221
- const upper = valeur.toUpperCase().replace(/[^A-Z0-9/]/g, '')
222
- const chiffres = upper.replace(/[^0-9]/g, '').slice(0, 12)
223
-
224
- let base = ''
225
- if (chiffres.length > 0) base += chiffres.slice(0, 3)
226
- if (chiffres.length > 3) base += '-' + chiffres.slice(3, 4)
227
- if (chiffres.length > 4) base += '-' + chiffres.slice(4, 9)
228
- if (chiffres.length > 9) base += '-' + chiffres.slice(9, 12)
154
+ // Insérer chiffre et auto-ajout des tirets
155
+ e.preventDefault()
229
156
 
230
- if (!activerExtension || base.length < 15) return base
157
+ const value = codeBudgetaire.value.replace(/-/g, '')
158
+ const clean = value.slice(0, 12) + e.key
231
159
 
232
- const reste = upper.slice(chiffres.length).replace(/[^A-Z0-9/]/gi, '')
160
+ let formatted = ''
161
+ if (clean.length > 0) formatted += clean.slice(0, 3)
162
+ if (clean.length > 3) formatted += '-' + clean.slice(3, 4)
163
+ if (clean.length > 4) formatted += '-' + clean.slice(4, 9)
164
+ if (clean.length > 9) formatted += '-' + clean.slice(9, 12)
233
165
 
234
- // Extraire les 7 premiers caractères restants pour l’extension
235
- let ext = reste.slice(0, 7).split('')
166
+ codeBudgetaire.value = formatted.slice(0, 15)
236
167
 
237
- // Ne garder que le premier slash s’il est à l’index 0 ou 3
238
- ext = ext.filter((c, i) => {
239
- if (c !== '/') return true
240
- return i === 0 || i === 3
241
- })
242
-
243
- // Enlever les slash non autorisés
244
- ext = ext.map((c, i) => {
245
- if (c === '/' && i !== 0 && i !== 3) return ''
246
- if (c !== '/' && !/^[A-Z0-9]$/i.test(c)) return ''
247
- return c
248
- })
168
+ nextTick(() => {
169
+ const newPos = codeBudgetaire.value.length
170
+ input.selectionStart = input.selectionEnd = newPos
171
+ })
249
172
 
250
- // Forcer le slash à la 4e position
251
- if (ext.length > 3) {
252
- ext[3] = '/'
253
- }
173
+ return
174
+ }
254
175
 
255
- // Réduire à 7 caractères
256
- ext = ext.slice(0, 7)
176
+ // --- Gestion de l'extension ---
177
+ if (!activerExtension || position >= 22 || codeBudgetaire.value.length >= 22) {
178
+ e.preventDefault()
179
+ return
180
+ }
257
181
 
258
- return (base + ext.join('')).slice(0, 22)
259
- }
182
+ const extensionPos = position - 15
260
183
 
261
- const gererPaste = (e: ClipboardEvent) => {
184
+ // Règle 1 : extension[0] = alphanum ou /
185
+ if (extensionPos === 0) {
186
+ if (!/^[A-Z0-9/]$/i.test(e.key)) {
262
187
  e.preventDefault()
263
- const clipboardData = e.clipboardData
264
- if (!clipboardData) return
265
- let pasted = clipboardData.getData('text') || ''
266
- codeBudgetaire.value = formaterCodeBudgetaire(pasted)
267
-
268
- setTimeout(() => {
269
- const input = e.target as HTMLInputElement
270
- input.selectionStart = input.selectionEnd = codeBudgetaire.value.length
271
- }, 0)
188
+ return
272
189
  }
190
+ return
191
+ }
273
192
 
274
- const sauvegarder = () => {
275
- codeBudgetaire.value = formaterCodeBudgetaire(codeBudgetaire.value)
276
-
277
- if (!estValideComplet.value) return
278
- if (codeBudgetaire.value === derniereValeurSauvegardee.value) return
279
-
280
- const codeNormalise = codeBudgetaire.value.trim().toUpperCase()
281
-
282
- const existe = props.codeBudgetairesProp.some(item => {
283
- const code = typeof item === 'string' ? item : item[0]
284
- return code.trim().toUpperCase() === codeNormalise
285
- })
286
-
287
- if (!existe) {
288
- const nouvelleListe = [...props.codeBudgetairesProp, codeBudgetaire.value]
289
- emit('update:codeBudgetairesProp', nouvelleListe)
290
- }
291
-
292
- derniereValeurSauvegardee.value = codeBudgetaire.value
293
- emit('update:modelValue', codeBudgetaire.value)
294
- }
295
-
296
- const extraireCode = (val: unknown): string => {
297
- if (val == null) return ''
298
- if (typeof val === 'string') return val
299
-
300
- // Cas où Vuetify enverrait { code, label }
301
- if (typeof val === 'object' && 'code' in (val as Record<string, unknown>)) {
302
- const obj = val as { code?: unknown }
303
- return typeof obj.code === 'string' ? obj.code : String(obj.code ?? '')
304
- }
305
-
306
- return String(val)
193
+ // Règle 2 : extension[1,2,4,5,6] = alphanum
194
+ if ([1, 2, 4, 5, 6].includes(extensionPos)) {
195
+ if (!/^[A-Z0-9]$/i.test(e.key)) {
196
+ e.preventDefault()
197
+ return
307
198
  }
199
+ return
200
+ }
201
+
202
+ // Règle 3 : slash automatique à position 3 (index 18)
203
+ if (extensionPos === 3) {
204
+ e.preventDefault()
205
+ const before = codeBudgetaire.value.slice(0, position)
206
+ const after = codeBudgetaire.value.slice(position)
207
+ codeBudgetaire.value = before + '/' + after
208
+ nextTick(() => {
209
+ input.selectionStart = input.selectionEnd = position + 1
210
+ })
211
+ return
212
+ }
308
213
 
309
- const gererChangement = (val: unknown) => {
310
- const code = extraireCode(val)
311
- codeBudgetaire.value = formaterCodeBudgetaire(code)
312
-
313
- const valeurFormatee = codeBudgetaire.value.trim().toUpperCase()
214
+ // Tout autre cas = bloqué
215
+ e.preventDefault()
216
+ }
314
217
 
315
- const estDansListe = props.codeBudgetairesProp.some(item => {
316
- const codeItem = typeof item === 'string' ? item : item[0]
317
- return codeItem.trim().toUpperCase() === valeurFormatee
318
- })
218
+ const formaterCodeBudgetaire = (valeur: string): string => {
219
+ if (!valeur) return ''
319
220
 
320
- if (
321
- estDansListe &&
322
- valeurFormatee !== (derniereValeurSauvegardee.value ?? '').toUpperCase() &&
323
- estValideComplet.value
324
- ) {
325
- sauvegarder()
326
- }
327
- }
221
+ const upper = valeur.toUpperCase().replace(/[^A-Z0-9/]/g, '')
222
+ const chiffres = upper.replace(/[^0-9]/g, '').slice(0, 12)
223
+
224
+ let base = ''
225
+ if (chiffres.length > 0) base += chiffres.slice(0, 3)
226
+ if (chiffres.length > 3) base += '-' + chiffres.slice(3, 4)
227
+ if (chiffres.length > 4) base += '-' + chiffres.slice(4, 9)
228
+ if (chiffres.length > 9) base += '-' + chiffres.slice(9, 12)
229
+
230
+ if (!activerExtension || base.length < 15) return base
231
+
232
+ const reste = upper.slice(chiffres.length).replace(/[^A-Z0-9/]/gi, '')
233
+
234
+ // Extraire les 7 premiers caractères restants pour l’extension
235
+ let ext = reste.slice(0, 7).split('')
236
+
237
+ // Ne garder que le premier slash s’il est à l’index 0 ou 3
238
+ ext = ext.filter((c, i) => {
239
+ if (c !== '/') return true
240
+ return i === 0 || i === 3
241
+ })
242
+
243
+ // Enlever les slash non autorisés
244
+ ext = ext.map((c, i) => {
245
+ if (c === '/' && i !== 0 && i !== 3) return ''
246
+ if (c !== '/' && !/^[A-Z0-9]$/i.test(c)) return ''
247
+ return c
248
+ })
249
+
250
+ // Forcer le slash à la 4e position
251
+ if (ext.length > 3) {
252
+ ext[3] = '/'
253
+ }
254
+
255
+ // Réduire à 7 caractères
256
+ ext = ext.slice(0, 7)
257
+
258
+ return (base + ext.join('')).slice(0, 22)
259
+ }
260
+
261
+ const gererPaste = (e: ClipboardEvent) => {
262
+ e.preventDefault()
263
+ const clipboardData = e.clipboardData
264
+ if (!clipboardData) return
265
+ const pasted = clipboardData.getData('text') || ''
266
+ codeBudgetaire.value = formaterCodeBudgetaire(pasted)
267
+
268
+ setTimeout(() => {
269
+ const input = e.target as HTMLInputElement
270
+ input.selectionStart = input.selectionEnd = codeBudgetaire.value.length
271
+ }, 0)
272
+ }
273
+
274
+ const sauvegarder = () => {
275
+ codeBudgetaire.value = formaterCodeBudgetaire(codeBudgetaire.value)
276
+
277
+ if (!estValideComplet.value) return
278
+ if (codeBudgetaire.value === derniereValeurSauvegardee.value) return
279
+
280
+ const codeNormalise = codeBudgetaire.value.trim().toUpperCase()
281
+
282
+ const existe = props.codeBudgetairesProp.some(item => {
283
+ const code = typeof item === 'string' ? item : item[0]
284
+ return code.trim().toUpperCase() === codeNormalise
285
+ })
286
+
287
+ if (!existe) {
288
+ const nouvelleListe = [...props.codeBudgetairesProp, codeBudgetaire.value]
289
+ emit('update:codeBudgetairesProp', nouvelleListe)
290
+ }
291
+
292
+ derniereValeurSauvegardee.value = codeBudgetaire.value
293
+ emit('update:modelValue', codeBudgetaire.value)
294
+ }
295
+
296
+ const extraireCode = (val: unknown): string => {
297
+ if (val == null) return ''
298
+ if (typeof val === 'string') return val
299
+
300
+ // Cas où Vuetify enverrait { code, label }
301
+ if (typeof val === 'object' && 'code' in (val as Record<string, unknown>)) {
302
+ const obj = val as { code?: unknown }
303
+ return typeof obj.code === 'string' ? obj.code : String(obj.code ?? '')
304
+ }
305
+
306
+ return String(val)
307
+ }
308
+
309
+ const gererChangement = (val: unknown) => {
310
+ const code = extraireCode(val)
311
+ codeBudgetaire.value = formaterCodeBudgetaire(code)
312
+
313
+ const valeurFormatee = codeBudgetaire.value.trim().toUpperCase()
314
+
315
+ const estDansListe = props.codeBudgetairesProp.some(item => {
316
+ const codeItem = typeof item === 'string' ? item : item[0]
317
+ return codeItem.trim().toUpperCase() === valeurFormatee
318
+ })
319
+
320
+ if (
321
+ estDansListe &&
322
+ valeurFormatee !== (derniereValeurSauvegardee.value ?? '').toUpperCase() &&
323
+ estValideComplet.value
324
+ ) {
325
+ sauvegarder()
326
+ }
327
+ }
328
328
 
329
329
  watch(
330
330
  () => codeBudgetaire.value,
@@ -4,8 +4,9 @@
4
4
  :titre="props.titre"
5
5
  :operation-en-cours="operationEnCours"
6
6
  activator="supprimer"
7
- v-bind="$attrs"
8
7
  :largeur="props.largeur"
8
+ :est-dialogue-alerte="modeAlerte"
9
+ v-bind="$attrs"
9
10
  @ok="confirmer"
10
11
  @annuler="annuler"
11
12
  >
@@ -1,12 +1,15 @@
1
1
  <template>
2
2
  <v-date-input
3
3
  :model-value="dateInterne"
4
- v-bind="$attrs"
4
+ bg-color="white"
5
+ color="primary"
5
6
  input-format="yyyy-MM-dd"
6
7
  variant="outlined"
7
8
  prepend-icon=""
8
9
  prepend-inner-icon="$calendar"
9
10
  density="comfortable"
11
+ :picker-props="{ color: 'accent' }"
12
+ v-bind="$attrs"
10
13
  @update:model-value="choixUtilisateur"
11
14
  />
12
15
  </template>
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <v-dialog
3
3
  v-model="dialog"
4
- v-bind="$attrs"
5
4
  class="pa-0 ma-0"
6
5
  :width="largeur"
7
6
  :fullscreen="display.xs.value"
8
7
  max-width="650"
9
8
  :persistent="props.persistant"
9
+ v-bind="$attrs"
10
10
  @keydown.esc="!persistant ? annuler : ''"
11
11
  @click:outside="!persistant ? annuler : ''"
12
12
  >
@@ -16,12 +16,13 @@
16
16
  icon="mdi-close"
17
17
  variant="text"
18
18
  class="position-absolute iconeHover"
19
- style="top: 5px; right: 5px"
19
+ color="primary"
20
+ style="right: 5px; top: 5px"
20
21
  @click="annuler"
21
22
  ></v-btn>
22
23
 
23
24
  <v-card-title
24
- class="pa-0 ma-0 pb-6"
25
+ class="pa-0 ma-0 pb-6 headline"
25
26
  style="font-size: 24px; white-space: normal; word-break: break-word"
26
27
  >
27
28
  <slot name="titre"></slot>
@@ -49,7 +50,7 @@
49
50
  <v-btn
50
51
  v-if="btnOk"
51
52
  class="Gouttiere"
52
- color="primary"
53
+ :color="props.estDialogueAlerte ? 'rouge' : 'primary'"
53
54
  :loading="operationEnCours"
54
55
  :disabled="btnOkDesactiver"
55
56
  variant="flat"
@@ -79,6 +80,7 @@
79
80
  btnOkTexte: { type: String, default: '' },
80
81
  titre: { type: String, default: '' },
81
82
  btnOkDesactiver: { type: Boolean, default: false },
83
+ estDialogueAlerte: { type: Boolean, default: false },
82
84
  })
83
85
 
84
86
  // Déclaration des événements émis
@@ -2,11 +2,11 @@
2
2
  <div class="editor">
3
3
  <Editor
4
4
  v-if="editorReady"
5
- v-bind="$attrs"
6
5
  v-model="editorValue"
7
6
  :init="initOptions"
8
7
  :disabled="desactiver"
9
8
  license-key="gpl"
9
+ v-bind="$attrs"
10
10
  @blur="onBlur"
11
11
  @keydown="onUserActivity"
12
12
  @change="onUserActivity"