codevdesign 0.0.77 → 0.0.78

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,330 +1,362 @@
1
- <template>
2
- <div class="pa-2 mt-2 mb-1 mr-1">
3
- <!--on affiche une div avec les infos de préférences si le user a déjà au moins une préférence, au moins une unité et si activerDiv est à true.-->
4
- <div v-if="preferences && unites && unites.length > 0 && activerDivPreferences">
5
- <v-card
6
- width="375"
7
- border
8
- >
9
- <v-card-text
10
- flat
11
- class="pt-0 mt-0"
12
- >
13
- <v-progress-linear
14
- v-if="chargementEnCours"
15
- indeterminate
16
- />
17
- <div
18
- v-if="!chargementEnCours"
19
- class="pt-2"
20
- >
21
- <div class="text-overline text-h6 mb-2">{{ texteTitre }}</div>
22
- <!-- <div v-if="existePreference == false">
23
- Cliquer sur modifier ou lors de la soumission, vous pourrez sélectionner vos préférences de suivi.
24
- </div>-->
25
- <div>
26
- <v-list-item
27
- v-for="uniteId in Object.keys(dictChaisesReleve).map(Number)"
28
- :key="uniteId"
29
- class="mb-1"
30
- >
31
- <chaiseItem
32
- :unite-id="uniteId"
33
- :preferences="preferences"
34
- :dict-chaises-releve="dictChaisesReleve"
35
- :unites="unites"
36
- />
37
- </v-list-item>
38
- </div>
39
- </div>
40
- </v-card-text>
41
- <v-card-actions>
42
- <div class="flex-grow-1"></div>
43
- <v-btn
44
- v-if="chargementEnCours == false"
45
- rounded
46
- variant="outlined"
47
- size="small"
48
- @click.stop="modifier"
49
- >{{ $t('csqc.bouton.modifier') }}</v-btn
50
- >
51
- </v-card-actions>
52
- </v-card>
53
- </div>
54
-
55
- <v-dialog
56
- v-model="visible"
57
- max-width="largeur"
58
- :fullscreen="display.name.value == 'xs'"
59
- @click:outside="annuler"
60
- @keydown.esc="annuler"
61
- >
62
- <v-card :class="['pa-0', display.name.value != 'xs' ? 'v-card-color-solid' : 'v-card-color-solid-xs']">
63
- <v-container :class="display.name.value == 'xs' ? 'pl-1 pr-3' : ''">
64
- <h3 class="pb-3 pl-2">{{ texteTitre }}</h3>
65
- <hr class="pl-2" />
66
- <v-card-text flat>
67
- <i>{{ info }}</i>
68
- <v-progress-linear
69
- v-if="chargementEnCours"
70
- indeterminate
71
- />
72
- <div
73
- v-if="!chargementEnCours"
74
- class="pt-4"
75
- >
76
- <v-row v-if="toutesUnitesPreferencesSelectionnees === false">
77
- <v-col cols="12">
78
- <v-alert
79
- v-model="afficherErreur"
80
- closable
81
- type="error"
82
- >{{ $t('csqc.message.chaiseSelectionToutes') }}</v-alert
83
- >
84
- </v-col>
85
- </v-row>
86
- <v-row>
87
- <v-col
88
- v-for="uniteId in Object.keys(dictChaisesReleve).map(Number)"
89
- :key="uniteId"
90
- cols="12"
91
- sm="4"
92
- md="3"
93
- >
94
- <label>{{ getUnite(uniteId)?.nom || '' }}</label>
95
- <br />
96
- <v-radio-group v-model="selection[uniteId]">
97
- <v-radio
98
- v-for="chaise in dictChaisesReleve[uniteId]"
99
- :key="chaise.id"
100
- :label="chaise.nom"
101
- :value="chaise.id"
102
- ></v-radio>
103
- </v-radio-group>
104
- </v-col>
105
- </v-row>
106
- </div>
107
- </v-card-text>
108
- </v-container>
109
-
110
- <v-card-actions>
111
- <div class="flex-grow-1"></div>
112
- <v-btn
113
- color="primary"
114
- variant="outlined"
115
- @click.stop="annuler"
116
- >Annuler</v-btn
117
- >
118
- <v-btn
119
- color="primary"
120
- @click.stop="ok"
121
- >Ok</v-btn
122
- >
123
- </v-card-actions>
124
- </v-card>
125
- </v-dialog>
126
- </div>
127
- </template>
128
-
129
- <script lang="ts" setup>
130
- import { ref, computed, onMounted } from 'vue'
131
- import axios from '@/outils/appAxios.ts'
132
- import chaiseItem from './chaiseItem.vue'
133
- import { useDisplay } from 'vuetify'
134
- const display = useDisplay()
135
-
136
- // Définition des props
137
- const props = defineProps<{
138
- activerDivPreferences: boolean
139
- typeintervenant: string
140
- demandeid: string
141
- formulaireid: string
142
- urlbase: string
143
- titre?: string
144
- texteinfo?: string
145
- largeur?: number
146
- }>()
147
-
148
- // Définition des emits
149
- const emit = defineEmits<{
150
- (event: 'annuler'): void
151
- (event: 'confirmer'): void
152
- }>()
153
-
154
- // Variables réactives
155
- const visible = ref(false)
156
- const chargementEnCours = ref(false)
157
- const afficherErreur = ref(false)
158
- const unites = ref<{ id: number; nom: string }[]>([])
159
- const preferences = ref<{ uniteId: number; chaiseId: number }[]>([])
160
- const dictChaisesReleve = ref<Record<number, { id: number; nom: string }[]>>({})
161
- const selection = ref<Record<number, number>>({})
162
- const modeModifier = ref(false)
163
-
164
- // Méthodes
165
- const soumettre = async () => {
166
- modeModifier.value = false
167
- await ouvrir()
168
- }
169
-
170
- const ouvrir = async () => {
171
- // Mode sans les divs
172
- if (props.activerDivPreferences === false) {
173
- await chargementPreferences()
174
- visible.value = true
175
- return
176
- }
177
-
178
- // Mode avec div, mais il manque une sélection
179
- if (!toutesUnitesPreferencesSelectionnees.value) {
180
- visible.value = true
181
- return
182
- }
183
-
184
- // Tout est beau
185
- await ok()
186
- }
187
-
188
- const definitionSelectionDepart = () => {
189
- for (const uniteId in dictChaisesReleve.value) {
190
- const chaises = dictChaisesReleve.value[uniteId]
191
- const uniteIdNum = Number(uniteId) // Convert to number
192
-
193
- const pref = preferences.value.find(
194
- pref => pref.uniteId === uniteIdNum && chaises.some(chaise => chaise.id === pref.chaiseId),
195
- )
196
-
197
- const chaiseIdDefaut = pref?.chaiseId ?? (chaises.length === 1 ? chaises[0].id : -1)
198
- selection.value[uniteIdNum] = chaiseIdDefaut // Ensure key consistency
199
- }
200
- }
201
- const estPrefere = (uniteId: number, chaiseId: number) => {
202
- return preferences.value.some(x => x.uniteId === uniteId && x.chaiseId === chaiseId)
203
- }
204
-
205
- const annuler = () => {
206
- visible.value = false
207
- modeModifier.value = false
208
- emit('annuler')
209
- }
210
-
211
- const getUnite = (uniteId: number) => {
212
- return unites.value.find(x => x.id === uniteId)
213
- }
214
-
215
- const modifier = () => {
216
- modeModifier.value = true
217
- visible.value = true
218
- }
219
-
220
- const ok = async () => {
221
- await sauvegarder()
222
- if (toutesUnitesPreferencesSelectionnees.value) {
223
- if (!modeModifier.value) {
224
- emit('confirmer')
225
- }
226
- visible.value = false
227
- modeModifier.value = false
228
- } else {
229
- afficherErreur.value = true
230
- }
231
- }
232
-
233
- const sauvegarder = async () => {
234
- for (const uniteId in dictChaisesReleve.value) {
235
- const chaiseId = selection.value[uniteId]
236
- if (chaiseId <= 0) {
237
- continue
238
- }
239
-
240
- // Cibler l'ancienne préférence reliée à une des chaises de cette unité
241
- let prefIndexDeUnite = -1
242
- for (let i = 0; i < dictChaisesReleve.value[uniteId].length; i++) {
243
- prefIndexDeUnite = preferences.value.findIndex(p => p.chaiseId === dictChaisesReleve.value[uniteId][i].id)
244
- if (prefIndexDeUnite >= 0) {
245
- break
246
- }
247
- }
248
-
249
- try {
250
- const response = await axios
251
- .getAxios()
252
- .put(
253
- `${props.urlbase}/api/ComposantUI/Preferences/${props.formulaireid}/Unite/${uniteId}/Chaise/${chaiseId}/TypeIntervenant/${props.typeintervenant}`,
254
- )
255
-
256
- const itemRecu = response.data // Extract the actual data
257
-
258
- // Écraser l'ancienne sélection
259
- if (prefIndexDeUnite >= 0) {
260
- preferences.value[prefIndexDeUnite] = itemRecu
261
- } else {
262
- preferences.value = [itemRecu]
263
- }
264
- } catch (e) {
265
- console.error(e)
266
- }
267
- }
268
- }
269
-
270
- const chargementPreferences = async () => {
271
- chargementEnCours.value = true
272
- // Ramasse les infos des chaises par unité
273
- dictChaisesReleve.value = await axios
274
- .getAxios()
275
- .get(`${props.urlbase}/api/ComposantUI/ReleveDe/${props.typeintervenant}/Demande/${props.demandeid}`)
276
-
277
- // Ramasse les préférences de l'usager
278
- preferences.value = await axios
279
- .getAxios()
280
- .get(
281
- `${props.urlbase}/api/ComposantUI/Preferences/${props.formulaireid}/TypeIntervenant/${props.typeintervenant}`,
282
- )
283
- definitionSelectionDepart()
284
-
285
- await sauvegarder() // Immédiatement on sauvegarde pour les choix uniques.
286
-
287
- chargementEnCours.value = false
288
- }
289
-
290
- const texteTitre = computed(() => {
291
- return props.titre || ''
292
- })
293
-
294
- const info = computed(() => {
295
- return props.texteinfo || ''
296
- })
297
-
298
- const existePreference = computed(() => {
299
- for (const uniteId in dictChaisesReleve.value) {
300
- for (let i = 0; i < dictChaisesReleve.value[uniteId].length; i++) {
301
- if (preferences.value.some(p => p.chaiseId === dictChaisesReleve.value[uniteId][i].id)) {
302
- return true
303
- }
304
- }
305
- }
306
- return false
307
- })
308
-
309
- const toutesUnitesPreferencesSelectionnees = computed(() => {
310
- for (const uniteId in dictChaisesReleve.value) {
311
- let uniteOk = false
312
- for (let i = 0; i < dictChaisesReleve.value[uniteId].length; i++) {
313
- if (preferences.value.some(p => p.chaiseId === dictChaisesReleve.value[uniteId][i].id)) {
314
- uniteOk = true
315
- }
316
- }
317
-
318
- if (!uniteOk) return false
319
- }
320
-
321
- return true // Toutes les unités ont été sélectionnées
322
- })
323
-
324
- onMounted(async () => {
325
- chargementEnCours.value = true
326
- // Ramasse les unités de l'usager
327
- unites.value = await axios.getAxios().get(`${props.urlbase}/api/ComposantUI/Unites`)
328
- chargementPreferences()
329
- })
330
- </script>
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 #contenu>
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' // <- adapte si besoin (ex: axios.getAxios())
122
+ import type { Unite } from '@/codev/modeles/unite'
123
+ import { useI18n } from 'vue-i18n'
124
+
125
+ interface Chaise {
126
+ id: number
127
+ nom: string
128
+ }
129
+ interface Preference {
130
+ uniteId: number
131
+ chaiseId: number
132
+ }
133
+ const modale = ref<InstanceType<typeof csqcDialogue> | null>(null)
134
+ /** Props */
135
+ const props = defineProps<{
136
+ activerDivPreferences?: boolean
137
+ typeIntervenant: number
138
+ demandeId: number
139
+ formulaireId: number
140
+ urlBase: string
141
+ texteTitre?: string
142
+ texteInfo?: string
143
+ largeurModale?: number
144
+ }>()
145
+ const { typeIntervenant, demandeId, formulaireId, urlBase } = toRefs(props)
146
+ /** Emits */
147
+ const emit = defineEmits<{
148
+ (e: 'annuler'): void
149
+ (e: 'confirmer'): void
150
+ }>()
151
+
152
+ const { t } = useI18n({ useScope: 'global' })
153
+ const { xs } = useDisplay()
154
+ const isXs = computed(() => xs.value)
155
+
156
+ /** State */
157
+ const visible = ref(false)
158
+ const chargementEnCours = ref(false)
159
+ const afficherErreur = ref(false)
160
+ const unites = ref<Unite[]>([])
161
+ const preferences = ref<Preference[]>([])
162
+ const dictChaisesReleve = ref<Record<string, Chaise[]>>({})
163
+ const selection = ref<Record<string, number>>({})
164
+ const modeModifier = ref(false)
165
+
166
+ /** Textes */
167
+ const texteMessageErreur = computed(() => t('csqc.csqcChaise.erreur'))
168
+ const texteBoutonAnnuler = computed(() => t('csqc.bouton.annuler'))
169
+ const texteBoutonModifier = computed(() => t('csqc.bouton.modifier'))
170
+ const texteTitre = computed(() =>
171
+ props.texteTitre && props.texteTitre.length > 0 ? props.texteTitre : t('csqc.csqcChaise.titre'),
172
+ )
173
+ const info = computed(() =>
174
+ props.texteInfo && props.texteInfo.length > 0 ? props.texteInfo : t('csqc.csqcChaise.info'),
175
+ )
176
+
177
+ // Option A — ne recharger que si typeIntervenant change
178
+
179
+ const largeur = computed(() => props.largeurModale ?? 1200)
180
+ const activerDivPreferences = computed(() => props.activerDivPreferences ?? true)
181
+
182
+ function getUnite(uniteId: string) {
183
+ return unites.value.find((u: Unite) => String(u.id) === String(uniteId))
184
+ }
185
+
186
+ /*
187
+ function estPrefere(uniteId: string | number, chaiseId: number) {
188
+ return preferences.value.some(p => String(p.uniteId) === String(uniteId) && p.chaiseId === chaiseId)
189
+ }*/
190
+
191
+ /** Sélection par défaut à partir des préférences existantes */
192
+ function definitionSelectionDepart() {
193
+ for (const uniteId in dictChaisesReleve.value) {
194
+ const chaises = dictChaisesReleve.value[uniteId] ?? []
195
+ const pref = preferences.value.find(
196
+ p => String(p.uniteId) === String(uniteId) && chaises.some(chaise => chaise.id === p.chaiseId),
197
+ )
198
+ const chaiseIdDefaut = pref?.chaiseId ?? (chaises.length === 1 ? (chaises[0]?.id ?? -1) : -1)
199
+ selection.value[uniteId] = chaiseIdDefaut
200
+ }
201
+ }
202
+
203
+ /** Toutes les unités ont-elles une préférence sélectionnée ? */
204
+ const toutesUnitesPreferencesSelectionnees = computed(() => {
205
+ for (const uniteId in dictChaisesReleve.value) {
206
+ const chaises = dictChaisesReleve.value[uniteId] ?? []
207
+ const uniteOk = chaises.some(c => preferences.value.some(p => p.chaiseId === c.id))
208
+ if (!uniteOk) return false
209
+ }
210
+ return true
211
+ })
212
+
213
+ async function chargerUnites() {
214
+ const url = `${props.urlBase}/api/ComposantUI/Unites`
215
+ const unitesData = (await axios.getAxios().get<Unite[]>(url)) as unknown as Unite[]
216
+ unites.value = unitesData ?? []
217
+ }
218
+
219
+ async function chargementPreferences() {
220
+ chargementEnCours.value = true
221
+
222
+ // Chaises par unité
223
+ {
224
+ const data = (await axios
225
+ .getAxios()
226
+ .get<
227
+ Record<string, Chaise[]>
228
+ >(`${props.urlBase}/api/ComposantUI/ReleveDe/${props.typeIntervenant}/Demande/${props.demandeId}`)) as unknown as Record<
229
+ string,
230
+ Chaise[]
231
+ >
232
+ dictChaisesReleve.value = data ?? {}
233
+ }
234
+
235
+ // Préférences de l'usager
236
+ {
237
+ const data = (await axios
238
+ .getAxios()
239
+ .get<
240
+ Preference[]
241
+ >(`${props.urlBase}/api/ComposantUI/Preferences/${props.formulaireId}/TypeIntervenant/${props.typeIntervenant}`)) as unknown as Preference[]
242
+ preferences.value = (data ?? []).filter(Boolean)
243
+ }
244
+
245
+ definitionSelectionDepart()
246
+
247
+ // Sauvegarde immédiate pour les choix uniques (si demandé par ton flux)
248
+ await sauvegarder()
249
+
250
+ chargementEnCours.value = false
251
+ }
252
+
253
+ /** Actions UI */
254
+ /*async function soumettre() {
255
+ modeModifier.value = false
256
+ await ouvrir()
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
+
321
+ /** Validation finale */
322
+ async function ok() {
323
+ await sauvegarder()
324
+
325
+ if (toutesUnitesPreferencesSelectionnees.value) {
326
+ if (!modeModifier.value) emit('confirmer')
327
+ visible.value = false
328
+ modeModifier.value = false
329
+ } else {
330
+ afficherErreur.value = true
331
+ await nextTick()
332
+ }
333
+ }
334
+
335
+ onMounted(async () => {
336
+ chargementEnCours.value = true
337
+ await chargerUnites()
338
+ await chargementPreferences()
339
+ chargementEnCours.value = false
340
+ })
341
+
342
+ // si le type d'intervenant change
343
+ watch(typeIntervenant, async (nv, ov) => {
344
+ if (nv === ov) return
345
+ await rechargerPourTypeIntervenant()
346
+ })
347
+
348
+ async function rechargerPourTypeIntervenant() {
349
+ try {
350
+ chargementEnCours.value = true
351
+ preferences.value = []
352
+ dictChaisesReleve.value = {}
353
+ selection.value = {}
354
+ afficherErreur.value = false
355
+
356
+ // recharge les données dépendantes
357
+ await chargementPreferences()
358
+ } finally {
359
+ chargementEnCours.value = false
360
+ }
361
+ }
362
+ </script>