codevdesign 1.0.25 → 1.0.27
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.
|
@@ -1,363 +1,367 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="pa-2 mt-2 mb-1 mr-1">
|
|
3
|
-
<!-- Affiche la carte récap si activée et qu'il y a des unités -->
|
|
4
|
-
<div v-if="activerDivPreferences && unites && unites.length > 0">
|
|
5
|
-
<v-card
|
|
6
|
-
width="375"
|
|
7
|
-
variant="outlined"
|
|
8
|
-
>
|
|
9
|
-
<v-card-text class="pt-0 mt-0">
|
|
10
|
-
<v-progress-linear
|
|
11
|
-
v-if="chargementEnCours"
|
|
12
|
-
indeterminate
|
|
13
|
-
/>
|
|
14
|
-
|
|
15
|
-
<div
|
|
16
|
-
v-else
|
|
17
|
-
class="pt-2"
|
|
18
|
-
>
|
|
19
|
-
<div class="text-overline text-h6 mb-2">{{ texteTitre }}</div>
|
|
20
|
-
|
|
21
|
-
<div>
|
|
22
|
-
<v-list-item
|
|
23
|
-
v-for="uniteId in Object.keys(dictChaisesReleve)"
|
|
24
|
-
:key="uniteId"
|
|
25
|
-
class="mb-1"
|
|
26
|
-
>
|
|
27
|
-
<ChaisePreferenceItem
|
|
28
|
-
:uniteId="Number(uniteId)"
|
|
29
|
-
:preferences="preferences"
|
|
30
|
-
:dictChaisesReleve="dictChaisesReleve"
|
|
31
|
-
:unites="unites"
|
|
32
|
-
/>
|
|
33
|
-
</v-list-item>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</v-card-text>
|
|
37
|
-
|
|
38
|
-
<v-card-actions>
|
|
39
|
-
<div class="flex-grow-1" />
|
|
40
|
-
<v-btn
|
|
41
|
-
v-if="!chargementEnCours"
|
|
42
|
-
rounded
|
|
43
|
-
variant="outlined"
|
|
44
|
-
size="small"
|
|
45
|
-
@click.stop="modifier"
|
|
46
|
-
>
|
|
47
|
-
{{ texteBoutonModifier }}
|
|
48
|
-
</v-btn>
|
|
49
|
-
</v-card-actions>
|
|
50
|
-
</v-card>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<csqcDialogue
|
|
54
|
-
ref="modale"
|
|
55
|
-
:operation-en-cours="chargementEnCours"
|
|
56
|
-
:btn-ok-desactiver="chargementEnCours"
|
|
57
|
-
:titre="texteTitre"
|
|
58
|
-
:btn-annuler-texte="texteBoutonAnnuler"
|
|
59
|
-
@annuler="annuler"
|
|
60
|
-
@ok="ok"
|
|
61
|
-
><template #content>
|
|
62
|
-
<div class="pt-2"></div>
|
|
63
|
-
<hr class="pt-0 mt-0 pl-0" />
|
|
64
|
-
<div class="pt-4">
|
|
65
|
-
<i>{{ info }}</i>
|
|
66
|
-
|
|
67
|
-
<v-progress-linear
|
|
68
|
-
v-if="chargementEnCours"
|
|
69
|
-
indeterminate
|
|
70
|
-
/>
|
|
71
|
-
|
|
72
|
-
<div
|
|
73
|
-
v-else
|
|
74
|
-
class="pt-4"
|
|
75
|
-
>
|
|
76
|
-
<v-row v-if="!toutesUnitesPreferencesSelectionnees">
|
|
77
|
-
<v-col cols="12">
|
|
78
|
-
<v-alert
|
|
79
|
-
v-model="afficherErreur"
|
|
80
|
-
type="error"
|
|
81
|
-
variant="tonal"
|
|
82
|
-
dismissible
|
|
83
|
-
>
|
|
84
|
-
{{ texteMessageErreur }}
|
|
85
|
-
</v-alert>
|
|
86
|
-
</v-col>
|
|
87
|
-
</v-row>
|
|
88
|
-
|
|
89
|
-
<v-row>
|
|
90
|
-
<v-col
|
|
91
|
-
v-for="uniteId in Object.keys(dictChaisesReleve)"
|
|
92
|
-
:key="uniteId"
|
|
93
|
-
cols="12"
|
|
94
|
-
sm="6"
|
|
95
|
-
md="4"
|
|
96
|
-
>
|
|
97
|
-
<label>{{ getUnite(uniteId)?.nom ?? '' }}</label>
|
|
98
|
-
<br />
|
|
99
|
-
<v-radio-group v-model="selection[uniteId]">
|
|
100
|
-
<v-radio
|
|
101
|
-
v-for="chaise in dictChaisesReleve[uniteId]"
|
|
102
|
-
:key="chaise.id"
|
|
103
|
-
:label="chaise.nom"
|
|
104
|
-
:value="chaise.id"
|
|
105
|
-
/>
|
|
106
|
-
</v-radio-group>
|
|
107
|
-
</v-col>
|
|
108
|
-
</v-row>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
</template>
|
|
112
|
-
</csqcDialogue>
|
|
113
|
-
</div>
|
|
114
|
-
</template>
|
|
115
|
-
|
|
116
|
-
<script setup lang="ts">
|
|
117
|
-
import { ref, computed, onMounted, nextTick, watch, toRefs } from 'vue'
|
|
118
|
-
import { useDisplay } from 'vuetify'
|
|
119
|
-
import ChaisePreferenceItem from './chaiseItem.vue'
|
|
120
|
-
import csqcDialogue from '../csqcDialogue.vue'
|
|
121
|
-
import axios from '../../outils/appAxios'
|
|
122
|
-
import type { Unite } from '@/codev/modeles/unite'
|
|
123
|
-
import { useI18n } from 'vue-i18n'
|
|
124
|
-
const modale = ref<InstanceType<typeof csqcDialogue> | null>(null)
|
|
125
|
-
|
|
126
|
-
interface Chaise {
|
|
127
|
-
id: number
|
|
128
|
-
nom: string
|
|
129
|
-
}
|
|
130
|
-
interface Preference {
|
|
131
|
-
uniteId: number
|
|
132
|
-
chaiseId: number
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** Props */
|
|
136
|
-
const props = defineProps<{
|
|
137
|
-
activerDivPreferences?: boolean
|
|
138
|
-
typeIntervenant: number
|
|
139
|
-
demandeId: number
|
|
140
|
-
formulaireId: number
|
|
141
|
-
urlBase: string
|
|
142
|
-
texteTitre?: string
|
|
143
|
-
texteInfo?: string
|
|
144
|
-
largeurModale?: number
|
|
145
|
-
}>()
|
|
146
|
-
const { typeIntervenant, demandeId, formulaireId, urlBase } = toRefs(props)
|
|
147
|
-
/** Emits */
|
|
148
|
-
const emit = defineEmits<{
|
|
149
|
-
(e: 'annuler'): void
|
|
150
|
-
(e: 'confirmer'): void
|
|
151
|
-
}>()
|
|
152
|
-
|
|
153
|
-
const { t } = useI18n({ useScope: 'global' })
|
|
154
|
-
const { xs } = useDisplay()
|
|
155
|
-
const isXs = computed(() => xs.value)
|
|
156
|
-
|
|
157
|
-
/** State */
|
|
158
|
-
const visible = ref(false)
|
|
159
|
-
const chargementEnCours = ref(false)
|
|
160
|
-
const afficherErreur = ref(false)
|
|
161
|
-
const unites = ref<Unite[]>([])
|
|
162
|
-
const preferences = ref<Preference[]>([])
|
|
163
|
-
const dictChaisesReleve = ref<Record<string, Chaise[]>>({})
|
|
164
|
-
const selection = ref<Record<string, number>>({})
|
|
165
|
-
const modeModifier = ref(false)
|
|
166
|
-
|
|
167
|
-
/** Textes */
|
|
168
|
-
const texteMessageErreur = computed(() => t('csqc.csqcChaise.erreur'))
|
|
169
|
-
const texteBoutonAnnuler = computed(() => t('csqc.bouton.annuler'))
|
|
170
|
-
const texteBoutonModifier = computed(() => t('csqc.bouton.modifier'))
|
|
171
|
-
const texteTitre = computed(() =>
|
|
172
|
-
props.texteTitre && props.texteTitre.length > 0 ? props.texteTitre : t('csqc.csqcChaise.titre'),
|
|
173
|
-
)
|
|
174
|
-
const info = computed(() =>
|
|
175
|
-
props.texteInfo && props.texteInfo.length > 0 ? props.texteInfo : t('csqc.csqcChaise.info'),
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
// Option A — ne recharger que si typeIntervenant change
|
|
179
|
-
|
|
180
|
-
const largeur = computed(() => props.largeurModale ?? 1200)
|
|
181
|
-
const activerDivPreferences = computed(() => props.activerDivPreferences ?? true)
|
|
182
|
-
|
|
183
|
-
function getUnite(uniteId: string) {
|
|
184
|
-
return unites.value.find((u: Unite) => String(u.id) === String(uniteId))
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/*
|
|
188
|
-
function estPrefere(uniteId: string | number, chaiseId: number) {
|
|
189
|
-
return preferences.value.some(p => String(p.uniteId) === String(uniteId) && p.chaiseId === chaiseId)
|
|
190
|
-
}*/
|
|
191
|
-
|
|
192
|
-
/** Sélection par défaut à partir des préférences existantes */
|
|
193
|
-
function definitionSelectionDepart() {
|
|
194
|
-
for (const uniteId in dictChaisesReleve.value) {
|
|
195
|
-
const chaises = dictChaisesReleve.value[uniteId] ?? []
|
|
196
|
-
const pref = preferences.value.find(
|
|
197
|
-
p => String(p.uniteId) === String(uniteId) && chaises.some(chaise => chaise.id === p.chaiseId),
|
|
198
|
-
)
|
|
199
|
-
const chaiseIdDefaut = pref?.chaiseId ?? (chaises.length === 1 ? (chaises[0]?.id ?? -1) : -1)
|
|
200
|
-
selection.value[uniteId] = chaiseIdDefaut
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/** Toutes les unités ont-elles une préférence sélectionnée ? */
|
|
205
|
-
const toutesUnitesPreferencesSelectionnees = computed(() => {
|
|
206
|
-
for (const uniteId in dictChaisesReleve.value) {
|
|
207
|
-
const chaises = dictChaisesReleve.value[uniteId] ?? []
|
|
208
|
-
const uniteOk = chaises.some(c => preferences.value.some(p => p.chaiseId === c.id))
|
|
209
|
-
if (!uniteOk) return false
|
|
210
|
-
}
|
|
211
|
-
return true
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
async function
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
visible.value = true
|
|
263
|
-
return
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
modeModifier.value =
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
async function
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
1
|
+
<template>
|
|
2
|
+
<div class="pa-2 mt-2 mb-1 mr-1">
|
|
3
|
+
<!-- Affiche la carte récap si activée et qu'il y a des unités -->
|
|
4
|
+
<div v-if="activerDivPreferences && unites && unites.length > 0">
|
|
5
|
+
<v-card
|
|
6
|
+
width="375"
|
|
7
|
+
variant="outlined"
|
|
8
|
+
>
|
|
9
|
+
<v-card-text class="pt-0 mt-0">
|
|
10
|
+
<v-progress-linear
|
|
11
|
+
v-if="chargementEnCours"
|
|
12
|
+
indeterminate
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
v-else
|
|
17
|
+
class="pt-2"
|
|
18
|
+
>
|
|
19
|
+
<div class="text-overline text-h6 mb-2">{{ texteTitre }}</div>
|
|
20
|
+
|
|
21
|
+
<div>
|
|
22
|
+
<v-list-item
|
|
23
|
+
v-for="uniteId in Object.keys(dictChaisesReleve)"
|
|
24
|
+
:key="uniteId"
|
|
25
|
+
class="mb-1"
|
|
26
|
+
>
|
|
27
|
+
<ChaisePreferenceItem
|
|
28
|
+
:uniteId="Number(uniteId)"
|
|
29
|
+
:preferences="preferences"
|
|
30
|
+
:dictChaisesReleve="dictChaisesReleve"
|
|
31
|
+
:unites="unites"
|
|
32
|
+
/>
|
|
33
|
+
</v-list-item>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</v-card-text>
|
|
37
|
+
|
|
38
|
+
<v-card-actions>
|
|
39
|
+
<div class="flex-grow-1" />
|
|
40
|
+
<v-btn
|
|
41
|
+
v-if="!chargementEnCours"
|
|
42
|
+
rounded
|
|
43
|
+
variant="outlined"
|
|
44
|
+
size="small"
|
|
45
|
+
@click.stop="modifier"
|
|
46
|
+
>
|
|
47
|
+
{{ texteBoutonModifier }}
|
|
48
|
+
</v-btn>
|
|
49
|
+
</v-card-actions>
|
|
50
|
+
</v-card>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<csqcDialogue
|
|
54
|
+
ref="modale"
|
|
55
|
+
:operation-en-cours="chargementEnCours"
|
|
56
|
+
:btn-ok-desactiver="chargementEnCours"
|
|
57
|
+
:titre="texteTitre"
|
|
58
|
+
:btn-annuler-texte="texteBoutonAnnuler"
|
|
59
|
+
@annuler="annuler"
|
|
60
|
+
@ok="ok"
|
|
61
|
+
><template #content>
|
|
62
|
+
<div class="pt-2"></div>
|
|
63
|
+
<hr class="pt-0 mt-0 pl-0" />
|
|
64
|
+
<div class="pt-4">
|
|
65
|
+
<i>{{ info }}</i>
|
|
66
|
+
|
|
67
|
+
<v-progress-linear
|
|
68
|
+
v-if="chargementEnCours"
|
|
69
|
+
indeterminate
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<div
|
|
73
|
+
v-else
|
|
74
|
+
class="pt-4"
|
|
75
|
+
>
|
|
76
|
+
<v-row v-if="!toutesUnitesPreferencesSelectionnees">
|
|
77
|
+
<v-col cols="12">
|
|
78
|
+
<v-alert
|
|
79
|
+
v-model="afficherErreur"
|
|
80
|
+
type="error"
|
|
81
|
+
variant="tonal"
|
|
82
|
+
dismissible
|
|
83
|
+
>
|
|
84
|
+
{{ texteMessageErreur }}
|
|
85
|
+
</v-alert>
|
|
86
|
+
</v-col>
|
|
87
|
+
</v-row>
|
|
88
|
+
|
|
89
|
+
<v-row>
|
|
90
|
+
<v-col
|
|
91
|
+
v-for="uniteId in Object.keys(dictChaisesReleve)"
|
|
92
|
+
:key="uniteId"
|
|
93
|
+
cols="12"
|
|
94
|
+
sm="6"
|
|
95
|
+
md="4"
|
|
96
|
+
>
|
|
97
|
+
<label>{{ getUnite(uniteId)?.nom ?? '' }}</label>
|
|
98
|
+
<br />
|
|
99
|
+
<v-radio-group v-model="selection[uniteId]">
|
|
100
|
+
<v-radio
|
|
101
|
+
v-for="chaise in dictChaisesReleve[uniteId]"
|
|
102
|
+
:key="chaise.id"
|
|
103
|
+
:label="chaise.nom"
|
|
104
|
+
:value="chaise.id"
|
|
105
|
+
/>
|
|
106
|
+
</v-radio-group>
|
|
107
|
+
</v-col>
|
|
108
|
+
</v-row>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|
|
112
|
+
</csqcDialogue>
|
|
113
|
+
</div>
|
|
114
|
+
</template>
|
|
115
|
+
|
|
116
|
+
<script setup lang="ts">
|
|
117
|
+
import { ref, computed, onMounted, nextTick, watch, toRefs } from 'vue'
|
|
118
|
+
import { useDisplay } from 'vuetify'
|
|
119
|
+
import ChaisePreferenceItem from './chaiseItem.vue'
|
|
120
|
+
import csqcDialogue from '../csqcDialogue.vue'
|
|
121
|
+
import axios from '../../outils/appAxios'
|
|
122
|
+
import type { Unite } from '@/codev/modeles/unite'
|
|
123
|
+
import { useI18n } from 'vue-i18n'
|
|
124
|
+
const modale = ref<InstanceType<typeof csqcDialogue> | null>(null)
|
|
125
|
+
|
|
126
|
+
interface Chaise {
|
|
127
|
+
id: number
|
|
128
|
+
nom: string
|
|
129
|
+
}
|
|
130
|
+
interface Preference {
|
|
131
|
+
uniteId: number
|
|
132
|
+
chaiseId: number
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Props */
|
|
136
|
+
const props = defineProps<{
|
|
137
|
+
activerDivPreferences?: boolean
|
|
138
|
+
typeIntervenant: number
|
|
139
|
+
demandeId: number
|
|
140
|
+
formulaireId: number
|
|
141
|
+
urlBase: string
|
|
142
|
+
texteTitre?: string
|
|
143
|
+
texteInfo?: string
|
|
144
|
+
largeurModale?: number
|
|
145
|
+
}>()
|
|
146
|
+
const { typeIntervenant, demandeId, formulaireId, urlBase } = toRefs(props)
|
|
147
|
+
/** Emits */
|
|
148
|
+
const emit = defineEmits<{
|
|
149
|
+
(e: 'annuler'): void
|
|
150
|
+
(e: 'confirmer'): void
|
|
151
|
+
}>()
|
|
152
|
+
|
|
153
|
+
const { t } = useI18n({ useScope: 'global' })
|
|
154
|
+
const { xs } = useDisplay()
|
|
155
|
+
const isXs = computed(() => xs.value)
|
|
156
|
+
|
|
157
|
+
/** State */
|
|
158
|
+
const visible = ref(false)
|
|
159
|
+
const chargementEnCours = ref(false)
|
|
160
|
+
const afficherErreur = ref(false)
|
|
161
|
+
const unites = ref<Unite[]>([])
|
|
162
|
+
const preferences = ref<Preference[]>([])
|
|
163
|
+
const dictChaisesReleve = ref<Record<string, Chaise[]>>({})
|
|
164
|
+
const selection = ref<Record<string, number>>({})
|
|
165
|
+
const modeModifier = ref(false)
|
|
166
|
+
|
|
167
|
+
/** Textes */
|
|
168
|
+
const texteMessageErreur = computed(() => t('csqc.csqcChaise.erreur'))
|
|
169
|
+
const texteBoutonAnnuler = computed(() => t('csqc.bouton.annuler'))
|
|
170
|
+
const texteBoutonModifier = computed(() => t('csqc.bouton.modifier'))
|
|
171
|
+
const texteTitre = computed(() =>
|
|
172
|
+
props.texteTitre && props.texteTitre.length > 0 ? props.texteTitre : t('csqc.csqcChaise.titre'),
|
|
173
|
+
)
|
|
174
|
+
const info = computed(() =>
|
|
175
|
+
props.texteInfo && props.texteInfo.length > 0 ? props.texteInfo : t('csqc.csqcChaise.info'),
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
// Option A — ne recharger que si typeIntervenant change
|
|
179
|
+
|
|
180
|
+
const largeur = computed(() => props.largeurModale ?? 1200)
|
|
181
|
+
const activerDivPreferences = computed(() => props.activerDivPreferences ?? true)
|
|
182
|
+
|
|
183
|
+
function getUnite(uniteId: string) {
|
|
184
|
+
return unites.value.find((u: Unite) => String(u.id) === String(uniteId))
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
function estPrefere(uniteId: string | number, chaiseId: number) {
|
|
189
|
+
return preferences.value.some(p => String(p.uniteId) === String(uniteId) && p.chaiseId === chaiseId)
|
|
190
|
+
}*/
|
|
191
|
+
|
|
192
|
+
/** Sélection par défaut à partir des préférences existantes */
|
|
193
|
+
function definitionSelectionDepart() {
|
|
194
|
+
for (const uniteId in dictChaisesReleve.value) {
|
|
195
|
+
const chaises = dictChaisesReleve.value[uniteId] ?? []
|
|
196
|
+
const pref = preferences.value.find(
|
|
197
|
+
p => String(p.uniteId) === String(uniteId) && chaises.some(chaise => chaise.id === p.chaiseId),
|
|
198
|
+
)
|
|
199
|
+
const chaiseIdDefaut = pref?.chaiseId ?? (chaises.length === 1 ? (chaises[0]?.id ?? -1) : -1)
|
|
200
|
+
selection.value[uniteId] = chaiseIdDefaut
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Toutes les unités ont-elles une préférence sélectionnée ? */
|
|
205
|
+
const toutesUnitesPreferencesSelectionnees = computed(() => {
|
|
206
|
+
for (const uniteId in dictChaisesReleve.value) {
|
|
207
|
+
const chaises = dictChaisesReleve.value[uniteId] ?? []
|
|
208
|
+
const uniteOk = chaises.some(c => preferences.value.some(p => p.chaiseId === c.id))
|
|
209
|
+
if (!uniteOk) return false
|
|
210
|
+
}
|
|
211
|
+
return true
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
async function charger() {
|
|
215
|
+
await chargerUnites()
|
|
216
|
+
await chargementPreferences()
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function chargerUnites() {
|
|
220
|
+
const url = `${props.urlBase}/api/ComposantUI/Unites`
|
|
221
|
+
const unitesData = (await axios.getAxios().get<Unite[]>(url)) as unknown as Unite[]
|
|
222
|
+
unites.value = unitesData ?? []
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function chargementPreferences() {
|
|
226
|
+
chargementEnCours.value = true
|
|
227
|
+
|
|
228
|
+
// Chaises par unité
|
|
229
|
+
{
|
|
230
|
+
const data = (await axios
|
|
231
|
+
.getAxios()
|
|
232
|
+
.get<
|
|
233
|
+
Record<string, Chaise[]>
|
|
234
|
+
>(`${props.urlBase}/api/ComposantUI/ReleveDe/${props.typeIntervenant}/Demande/${props.demandeId}`)) as unknown as Record<
|
|
235
|
+
string,
|
|
236
|
+
Chaise[]
|
|
237
|
+
>
|
|
238
|
+
dictChaisesReleve.value = data ?? {}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Préférences de l'usager
|
|
242
|
+
{
|
|
243
|
+
const data = (await axios
|
|
244
|
+
.getAxios()
|
|
245
|
+
.get<
|
|
246
|
+
Preference[]
|
|
247
|
+
>(`${props.urlBase}/api/ComposantUI/Preferences/${props.formulaireId}/TypeIntervenant/${props.typeIntervenant}`)) as unknown as Preference[]
|
|
248
|
+
preferences.value = (data ?? []).filter(Boolean)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
definitionSelectionDepart()
|
|
252
|
+
|
|
253
|
+
// Sauvegarde immédiate pour les choix uniques (si demandé par ton flux)
|
|
254
|
+
await sauvegarder()
|
|
255
|
+
|
|
256
|
+
chargementEnCours.value = false
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function ouvrir() {
|
|
260
|
+
if (!activerDivPreferences.value) {
|
|
261
|
+
await chargementPreferences()
|
|
262
|
+
visible.value = true
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (!toutesUnitesPreferencesSelectionnees.value) {
|
|
267
|
+
visible.value = true
|
|
268
|
+
return
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
await ok()
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function annuler() {
|
|
275
|
+
visible.value = false
|
|
276
|
+
modeModifier.value = false
|
|
277
|
+
emit('annuler')
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function modifier() {
|
|
281
|
+
modeModifier.value = true
|
|
282
|
+
visible.value = true
|
|
283
|
+
modale.value?.ouvrir()
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function sauvegarder() {
|
|
287
|
+
for (const uniteId in dictChaisesReleve.value) {
|
|
288
|
+
const chaiseId = selection.value[uniteId]
|
|
289
|
+
if (!chaiseId || chaiseId <= 0) continue
|
|
290
|
+
|
|
291
|
+
const chaises = dictChaisesReleve.value[uniteId] ?? []
|
|
292
|
+
if (chaises.length === 0) continue
|
|
293
|
+
|
|
294
|
+
// Préférence existante pour CETTE unité ?
|
|
295
|
+
const prefIndexDeUnite = preferences.value.findIndex(p => chaises.some(c => c.id === p.chaiseId))
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
const data = (await axios
|
|
299
|
+
.getAxios()
|
|
300
|
+
.put<Preference>(
|
|
301
|
+
`${props.urlBase}/api/ComposantUI/Preferences/${props.formulaireId}` +
|
|
302
|
+
`/Unite/${encodeURIComponent(uniteId)}` +
|
|
303
|
+
`/Chaise/${chaiseId}` +
|
|
304
|
+
`/TypeIntervenant/${props.typeIntervenant}`,
|
|
305
|
+
)) as unknown as Preference
|
|
306
|
+
const itemRecu = data as Preference
|
|
307
|
+
|
|
308
|
+
if (prefIndexDeUnite >= 0) {
|
|
309
|
+
// remplace l'élément à l'index
|
|
310
|
+
preferences.value.splice(prefIndexDeUnite, 1, itemRecu)
|
|
311
|
+
} else {
|
|
312
|
+
// ajoute un nouvel élément
|
|
313
|
+
preferences.value.push(itemRecu)
|
|
314
|
+
}
|
|
315
|
+
} catch (e) {
|
|
316
|
+
console.error(e)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async function soumettre() {
|
|
321
|
+
modeModifier.value = false
|
|
322
|
+
await ouvrir()
|
|
323
|
+
}
|
|
324
|
+
/** Validation finale */
|
|
325
|
+
async function ok() {
|
|
326
|
+
await sauvegarder()
|
|
327
|
+
|
|
328
|
+
if (toutesUnitesPreferencesSelectionnees.value) {
|
|
329
|
+
if (!modeModifier.value) emit('confirmer')
|
|
330
|
+
visible.value = false
|
|
331
|
+
modeModifier.value = false
|
|
332
|
+
} else {
|
|
333
|
+
afficherErreur.value = true
|
|
334
|
+
await nextTick()
|
|
335
|
+
}
|
|
336
|
+
modale.value?.fermer()
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
onMounted(async () => {
|
|
340
|
+
chargementEnCours.value = true
|
|
341
|
+
await charger()
|
|
342
|
+
chargementEnCours.value = false
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
// si le type d'intervenant change
|
|
346
|
+
watch(typeIntervenant, async (nv, ov) => {
|
|
347
|
+
if (nv === ov) return
|
|
348
|
+
await rechargerPourTypeIntervenant()
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
async function rechargerPourTypeIntervenant() {
|
|
352
|
+
try {
|
|
353
|
+
chargementEnCours.value = true
|
|
354
|
+
preferences.value = []
|
|
355
|
+
dictChaisesReleve.value = {}
|
|
356
|
+
selection.value = {}
|
|
357
|
+
afficherErreur.value = false
|
|
358
|
+
|
|
359
|
+
// recharge les données dépendantes
|
|
360
|
+
await chargementPreferences()
|
|
361
|
+
} finally {
|
|
362
|
+
chargementEnCours.value = false
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
defineExpose({ charger, soumettre })
|
|
367
|
+
</script>
|
|
@@ -37,296 +37,300 @@
|
|
|
37
37
|
</template>
|
|
38
38
|
|
|
39
39
|
<script setup lang="ts">
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
+
})
|
|
67
78
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
}
|
|
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
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
const [code, nomBrut] = item
|
|
89
|
+
const nom = (nomBrut ?? '').toString().trim()
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
return { code, nom }
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
const placeholder = computed(() => {
|
|
96
|
+
const base = format.replace(/9/g, '0')
|
|
97
|
+
const extension = activerExtension ? '-XXX/XXX' : ''
|
|
98
|
+
return base + extension
|
|
99
|
+
})
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
105
|
|
|
106
|
-
|
|
106
|
+
if (!/^\d{3}-\d{1}-\d{5}-\d{3}$/.test(base)) return false
|
|
107
107
|
|
|
108
|
-
|
|
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
|
+
})
|
|
120
|
+
|
|
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
|
+
})
|
|
109
137
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (extension.length !== 7) return false
|
|
138
|
+
const caractereAutorises = (e: KeyboardEvent) => {
|
|
139
|
+
if (e.ctrlKey || e.metaKey) return
|
|
113
140
|
|
|
114
|
-
|
|
115
|
-
|
|
141
|
+
const touchesSpecifiques = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End']
|
|
142
|
+
if (touchesSpecifiques.includes(e.key)) return
|
|
116
143
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
})
|
|
144
|
+
const input = e.target as HTMLInputElement
|
|
145
|
+
let position = input.selectionStart ?? 0
|
|
120
146
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
+
}
|
|
125
153
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return () => rule(codeBudgetaire.value) // on passe la valeur formatée
|
|
129
|
-
}),
|
|
130
|
-
])
|
|
154
|
+
// Insérer chiffre et auto-ajout des tirets
|
|
155
|
+
e.preventDefault()
|
|
131
156
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!estValide.value) return false
|
|
135
|
-
return props.reglesSupp.every(rule => rule(codeBudgetaire.value) === true)
|
|
136
|
-
})
|
|
157
|
+
const value = codeBudgetaire.value.replace(/-/g, '')
|
|
158
|
+
const clean = value.slice(0, 12) + e.key
|
|
137
159
|
|
|
138
|
-
|
|
139
|
-
|
|
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)
|
|
140
165
|
|
|
141
|
-
|
|
142
|
-
if (touchesSpecifiques.includes(e.key)) return
|
|
166
|
+
codeBudgetaire.value = formatted.slice(0, 15)
|
|
143
167
|
|
|
144
|
-
|
|
145
|
-
|
|
168
|
+
nextTick(() => {
|
|
169
|
+
const newPos = codeBudgetaire.value.length
|
|
170
|
+
input.selectionStart = input.selectionEnd = newPos
|
|
171
|
+
})
|
|
146
172
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// --- Gestion de l'extension ---
|
|
177
|
+
if (!activerExtension || position >= 22 || codeBudgetaire.value.length >= 22) {
|
|
178
|
+
e.preventDefault()
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const extensionPos = position - 15
|
|
183
|
+
|
|
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
|
+
}
|
|
192
|
+
|
|
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
|
+
}
|
|
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
|
+
}
|
|
213
|
+
|
|
214
|
+
// Tout autre cas = bloqué
|
|
150
215
|
e.preventDefault()
|
|
151
|
-
return
|
|
152
216
|
}
|
|
153
217
|
|
|
154
|
-
|
|
155
|
-
|
|
218
|
+
const formaterCodeBudgetaire = (valeur: string): string => {
|
|
219
|
+
if (!valeur) return ''
|
|
156
220
|
|
|
157
|
-
|
|
158
|
-
|
|
221
|
+
const upper = valeur.toUpperCase().replace(/[^A-Z0-9/]/g, '')
|
|
222
|
+
const chiffres = upper.replace(/[^0-9]/g, '').slice(0, 12)
|
|
159
223
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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)
|
|
165
229
|
|
|
166
|
-
|
|
230
|
+
if (!activerExtension || base.length < 15) return base
|
|
167
231
|
|
|
168
|
-
|
|
169
|
-
const newPos = codeBudgetaire.value.length
|
|
170
|
-
input.selectionStart = input.selectionEnd = newPos
|
|
171
|
-
})
|
|
232
|
+
const reste = upper.slice(chiffres.length).replace(/[^A-Z0-9/]/gi, '')
|
|
172
233
|
|
|
173
|
-
|
|
174
|
-
|
|
234
|
+
// Extraire les 7 premiers caractères restants pour l’extension
|
|
235
|
+
let ext = reste.slice(0, 7).split('')
|
|
175
236
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
+
})
|
|
181
242
|
|
|
182
|
-
|
|
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
|
+
})
|
|
183
249
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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)
|
|
189
259
|
}
|
|
190
|
-
return
|
|
191
|
-
}
|
|
192
260
|
|
|
193
|
-
|
|
194
|
-
if ([1, 2, 4, 5, 6].includes(extensionPos)) {
|
|
195
|
-
if (!/^[A-Z0-9]$/i.test(e.key)) {
|
|
261
|
+
const gererPaste = (e: ClipboardEvent) => {
|
|
196
262
|
e.preventDefault()
|
|
197
|
-
|
|
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)
|
|
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)
|
|
198
307
|
}
|
|
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
|
-
}
|
|
213
308
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
309
|
+
const gererChangement = (val: unknown) => {
|
|
310
|
+
const code = extraireCode(val)
|
|
311
|
+
codeBudgetaire.value = formaterCodeBudgetaire(code)
|
|
217
312
|
|
|
218
|
-
|
|
219
|
-
if (!valeur) return ''
|
|
313
|
+
const valeurFormatee = codeBudgetaire.value.trim().toUpperCase()
|
|
220
314
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
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)
|
|
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
|
-
|
|
329
|
-
watch(estValideComplet, value => {
|
|
330
|
-
emit('update:valide', value)
|
|
331
|
-
})
|
|
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
|
+
|
|
329
|
+
watch(
|
|
330
|
+
() => codeBudgetaire.value,
|
|
331
|
+
() => {
|
|
332
|
+
emit('update:valide', estValideComplet.value)
|
|
333
|
+
},
|
|
334
|
+
{ immediate: true },
|
|
335
|
+
)
|
|
332
336
|
</script>
|