v-sistec-features 1.31.12 → 1.31.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/v-sistec-features.css +1 -1
- package/dist/vDataAgenda.d.ts +591 -17
- package/dist/vDataAgenda.js +3382 -3469
- package/package.json +1 -1
- package/src/DataAgenda/VDataAgenda.vue +122 -285
- package/src/DataAgenda/components/AgendaMatrix.vue +27 -18
- package/src/DataAgenda/components/AgendaMatrixBase.vue +93 -501
- package/src/DataAgenda/components/AgendaMatrixUnico.vue +18 -28
- package/src/DataAgenda/components/AgendaTabelaHorario.vue +105 -515
- package/src/DataAgenda/components/AgendaVueCal.vue +118 -199
- package/src/DataAgenda/components/ModalReserva.vue +200 -291
- package/src/DataAgenda/composables/useGradeCompartilhada.ts +216 -0
package/package.json
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
O layout raiz que orquestra a interface com cabeçalhos modulares separados.
|
|
4
4
|
Suporta os modos 'calendario', 'tabela' (matriz horizontal) e 'tabela-horario' (grade vertical de horários por turno).
|
|
5
5
|
Repassa as configurações de usuário, layout, recurso único opcional, blocos por agenda e o cliente HTTP para os filhos,
|
|
6
|
-
além de destacar a semana operacional ativa
|
|
6
|
+
além de destacar a semana operacional ativa, bloquear dias inativos no minicalendário lateral e expor a lista de
|
|
7
|
+
recursos atualmente em exibição no modelo ativo.
|
|
7
8
|
========
|
|
8
9
|
-->
|
|
9
10
|
<script setup lang="ts">
|
|
10
11
|
import { ref, computed, onMounted, provide } from 'vue';
|
|
11
12
|
import { VueCal } from 'vue-cal';
|
|
12
13
|
import 'vue-cal/style.css';
|
|
13
|
-
import { useAgenda } from './composables/useAgenda
|
|
14
|
+
import { useAgenda } from './composables/useAgenda';
|
|
15
|
+
import { calcularDataInicioSemana, formatarDataIso } from './composables/useGradeCompartilhada';
|
|
14
16
|
import AgendaVueCal from './components/AgendaVueCal.vue';
|
|
15
17
|
import AgendaMatrix from './components/AgendaMatrix.vue';
|
|
16
18
|
import AgendaMatrixUnico from './components/AgendaMatrixUnico.vue';
|
|
@@ -19,142 +21,131 @@ import HeaderCalendario from './components/HeaderCalendario.vue';
|
|
|
19
21
|
import HeaderTabela from './components/HeaderTabela.vue';
|
|
20
22
|
|
|
21
23
|
const props = withDefaults(defineProps<{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
modoLayout?: 'calendario' | 'tabela' | 'tabela-horario',
|
|
25
|
+
idRecursoUnico?: number | string | null,
|
|
26
|
+
usaInterceptador?: boolean,
|
|
27
|
+
usuarioLogado?: string,
|
|
28
|
+
tituloPadrao?: string,
|
|
29
|
+
ocultarTituloModal?: boolean,
|
|
30
|
+
configuracaoBlocos?: any,
|
|
31
|
+
fetch: any,
|
|
30
32
|
}>(), {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
modoLayout: 'calendario',
|
|
34
|
+
idRecursoUnico: null,
|
|
35
|
+
usaInterceptador: false,
|
|
36
|
+
usuarioLogado: '',
|
|
37
|
+
tituloPadrao: '',
|
|
38
|
+
ocultarTituloModal: false,
|
|
39
|
+
configuracaoBlocos: null
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
provide('api-instance-agenda', props.fetch);
|
|
43
|
+
defineEmits(['before-save']);
|
|
41
44
|
|
|
42
|
-
const emit = defineEmits(['before-save']);
|
|
43
|
-
|
|
44
|
-
// Armazena as referências e funções do composable de agenda para manipulação global.
|
|
45
45
|
const {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
dataSelecionada,
|
|
47
|
+
dataVisao,
|
|
48
|
+
agendasDisponiveis,
|
|
49
|
+
agendaSelecionada,
|
|
50
|
+
datasDesabilitadas,
|
|
51
|
+
carregarRecursosEAgendas
|
|
52
52
|
} = useAgenda(props.fetch);
|
|
53
53
|
|
|
54
|
-
// Controla o estado de abertura da barra lateral (menu) contendo o minicalendário.
|
|
55
54
|
const menuAberto = ref(true);
|
|
56
|
-
|
|
57
|
-
// Armazena a referência da instância do componente vue-cal em sua versão miniatura.
|
|
58
55
|
const calendarioMiniRef = ref<any>(null);
|
|
56
|
+
const modeloAtivoRef = ref<any>(null);
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Extrai de forma segura o objeto de data embutido na célula customizada do vue-cal.
|
|
67
|
-
const obterDataDaCelula = (cell: any): Date | null => {
|
|
68
|
-
if (!cell) return null;
|
|
69
|
-
if (cell instanceof Date) return cell;
|
|
70
|
-
if (cell.start) return new Date(cell.start);
|
|
71
|
-
return null;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Recebe um objeto Date e devolve a string formatada em YYYY-MM-DD local.
|
|
75
|
-
const formatarDataIsoCurta = (data: Date): string => {
|
|
76
|
-
const ano = data.getFullYear();
|
|
77
|
-
const mes = String(data.getMonth() + 1).padStart(2, '0');
|
|
78
|
-
const dia = String(data.getDate()).padStart(2, '0');
|
|
79
|
-
return `${ano}-${mes}-${dia}`;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Devolve um Set para consulta rápida contendo todas as datas desabilitadas da agenda atual.
|
|
83
|
-
const conjuntoDatasDesabilitadas = computed(() => {
|
|
84
|
-
return new Set<string>(datasDesabilitadas.value);
|
|
58
|
+
const componenteModeloAtivo = computed(() => {
|
|
59
|
+
if (props.modoLayout === 'calendario') return AgendaVueCal;
|
|
60
|
+
if (props.modoLayout === 'tabela-horario') return AgendaTabelaHorario;
|
|
61
|
+
if (props.modoLayout === 'tabela' && props.idRecursoUnico) return AgendaMatrixUnico;
|
|
62
|
+
return AgendaMatrix;
|
|
85
63
|
});
|
|
86
64
|
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
65
|
+
const propriedadesModeloAtivo = computed(() => {
|
|
66
|
+
const base = {
|
|
67
|
+
usaInterceptador: props.usaInterceptador,
|
|
68
|
+
tituloPadrao: props.tituloPadrao,
|
|
69
|
+
ocultarTituloModal: props.ocultarTituloModal
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (props.modoLayout === 'calendario') {
|
|
73
|
+
return { ...base, usuarioLogado: props.usuarioLogado };
|
|
74
|
+
}
|
|
75
|
+
if (props.modoLayout === 'tabela-horario') {
|
|
76
|
+
return { ...base, idRecursoUnico: props.idRecursoUnico, configuracaoBlocos: props.configuracaoBlocos };
|
|
77
|
+
}
|
|
78
|
+
if (props.modoLayout === 'tabela' && props.idRecursoUnico) {
|
|
79
|
+
return { ...base, idRecurso: props.idRecursoUnico, configuracaoBlocos: props.configuracaoBlocos };
|
|
80
|
+
}
|
|
81
|
+
return { ...base, configuracaoBlocos: props.configuracaoBlocos };
|
|
82
|
+
});
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
(a: any) => Number(a.id_agenda) === Number(agendaSelecionada.value)
|
|
96
|
-
);
|
|
97
|
-
if (!agendaObj || !agendaObj.detalhes) return visiveis;
|
|
84
|
+
const recursosEmExibicao = computed(() => modeloAtivoRef.value?.recursosEmExibicao ?? []);
|
|
98
85
|
|
|
99
|
-
|
|
100
|
-
const diasVisiveis = Number(agendaObj.detalhes.dias_visiveis_agenda ?? 6);
|
|
101
|
-
const diaInicioJs = (diaInicioPython + 1) % 7;
|
|
86
|
+
defineExpose({ recursosEmExibicao });
|
|
102
87
|
|
|
103
|
-
|
|
104
|
-
if (typeof dataSelecionada.value === 'string') {
|
|
105
|
-
const apenasData = String(dataSelecionada.value).substring(0, 10);
|
|
106
|
-
const [ano, mes, dia] = apenasData.split('-').map(Number);
|
|
107
|
-
dataBase = new Date(ano!, mes! - 1, dia!);
|
|
108
|
-
} else {
|
|
109
|
-
const d = new Date(dataSelecionada.value);
|
|
110
|
-
dataBase = new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
111
|
-
}
|
|
88
|
+
onMounted(() => { carregarRecursosEAgendas(); });
|
|
112
89
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
90
|
+
const obterDataDaCelula = (cell: any): Date | null => {
|
|
91
|
+
if (!cell) return null;
|
|
92
|
+
if (cell instanceof Date) return cell;
|
|
93
|
+
if (cell.start) return new Date(cell.start);
|
|
94
|
+
return null;
|
|
95
|
+
};
|
|
116
96
|
|
|
117
|
-
|
|
118
|
-
const diaCorrente = new Date(inicioSemana);
|
|
119
|
-
diaCorrente.setDate(inicioSemana.getDate() + i);
|
|
120
|
-
visiveis.add(formatarDataIsoCurta(diaCorrente));
|
|
121
|
-
}
|
|
97
|
+
const conjuntoDatasDesabilitadas = computed(() => new Set<string>(datasDesabilitadas.value));
|
|
122
98
|
|
|
99
|
+
const datasVisiveisNaSemana = computed(() => {
|
|
100
|
+
const visiveis = new Set<string>();
|
|
101
|
+
if (props.modoLayout !== 'tabela-horario' || !dataSelecionada.value || !agendaSelecionada.value) {
|
|
123
102
|
return visiveis;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const agendaObj = agendasDisponiveis.value.find(
|
|
106
|
+
(a: any) => Number(a.id_agenda) === Number(agendaSelecionada.value)
|
|
107
|
+
);
|
|
108
|
+
if (!agendaObj?.detalhes) return visiveis;
|
|
109
|
+
|
|
110
|
+
const inicioSemana = calcularDataInicioSemana(
|
|
111
|
+
dataSelecionada.value,
|
|
112
|
+
Number(agendaObj.detalhes.dia_inicio_semana_agenda ?? 0)
|
|
113
|
+
);
|
|
114
|
+
const diasVisiveis = Number(agendaObj.detalhes.dias_visiveis_agenda ?? 6);
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < diasVisiveis; i++) {
|
|
117
|
+
const diaCorrente = new Date(inicioSemana);
|
|
118
|
+
diaCorrente.setDate(inicioSemana.getDate() + i);
|
|
119
|
+
visiveis.add(formatarDataIso(diaCorrente));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return visiveis;
|
|
124
123
|
});
|
|
125
124
|
|
|
126
|
-
// Recebe a célula do minicalendário e devolve true se aquele dia da semana não funcionar na agenda.
|
|
127
125
|
const ehDiaBloqueadoNoMini = (cell: any): boolean => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
const data = obterDataDaCelula(cell);
|
|
127
|
+
if (!data || props.modoLayout !== 'tabela-horario') return false;
|
|
128
|
+
return conjuntoDatasDesabilitadas.value.has(formatarDataIso(data));
|
|
131
129
|
};
|
|
132
130
|
|
|
133
|
-
// Recebe a célula do minicalendário e devolve true se ela já estiver sendo exibida na tabela atual.
|
|
134
131
|
const ehDiaVisivelNaGrade = (cell: any): boolean => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
const data = obterDataDaCelula(cell);
|
|
133
|
+
if (!data || props.modoLayout !== 'tabela-horario') return false;
|
|
134
|
+
return datasVisiveisNaSemana.value.has(formatarDataIso(data));
|
|
138
135
|
};
|
|
139
136
|
|
|
140
|
-
// Recebe nada. Devolve nada.
|
|
141
|
-
// É usada para retrair ou expandir a aba esquerda de navegação rápida.
|
|
142
137
|
const alternarMenu = () => { menuAberto.value = !menuAberto.value; };
|
|
143
138
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (props.modoLayout === 'calendario') agendaVueCalRef.value?.irParaHoje();
|
|
151
|
-
if (calendarioMiniRef.value) calendarioMiniRef.value.view.goToToday();
|
|
139
|
+
const irParaHoje = () => {
|
|
140
|
+
const hoje = new Date();
|
|
141
|
+
dataSelecionada.value = hoje;
|
|
142
|
+
dataVisao.value = hoje;
|
|
143
|
+
if (props.modoLayout === 'calendario') modeloAtivoRef.value?.irParaHoje?.();
|
|
144
|
+
if (calendarioMiniRef.value) calendarioMiniRef.value.view.goToToday();
|
|
152
145
|
};
|
|
153
146
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const mudarVisao = (novaVisao: string) => {
|
|
157
|
-
agendaVueCalRef.value?.mudarVisao(novaVisao);
|
|
147
|
+
const mudarVisao = (novaVisao: string) => {
|
|
148
|
+
modeloAtivoRef.value?.mudarVisao?.(novaVisao);
|
|
158
149
|
};
|
|
159
150
|
</script>
|
|
160
151
|
|
|
@@ -227,207 +218,53 @@ const mudarVisao = (novaVisao: string) => {
|
|
|
227
218
|
</aside>
|
|
228
219
|
|
|
229
220
|
<main class="area-calendario">
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
ref="
|
|
233
|
-
|
|
234
|
-
:usuario-logado="props.usuarioLogado"
|
|
235
|
-
:titulo-padrao="props.tituloPadrao"
|
|
236
|
-
:ocultar-titulo-modal="props.ocultarTituloModal"
|
|
237
|
-
@before-save="$emit('before-save', $event)"
|
|
238
|
-
>
|
|
239
|
-
<template #campos-extras>
|
|
240
|
-
<slot name="campos-extras"></slot>
|
|
241
|
-
</template>
|
|
242
|
-
</AgendaVueCal>
|
|
243
|
-
|
|
244
|
-
<AgendaTabelaHorario
|
|
245
|
-
v-else-if="props.modoLayout === 'tabela-horario'"
|
|
246
|
-
:id-recurso-unico="props.idRecursoUnico"
|
|
247
|
-
:usa-interceptador="props.usaInterceptador"
|
|
248
|
-
:titulo-padrao="props.tituloPadrao"
|
|
249
|
-
:ocultar-titulo-modal="props.ocultarTituloModal"
|
|
250
|
-
:configuracao-blocos="props.configuracaoBlocos"
|
|
251
|
-
@before-save="$emit('before-save', $event)"
|
|
252
|
-
>
|
|
253
|
-
<template #campos-extras>
|
|
254
|
-
<slot name="campos-extras"></slot>
|
|
255
|
-
</template>
|
|
256
|
-
</AgendaTabelaHorario>
|
|
257
|
-
|
|
258
|
-
<AgendaMatrixUnico
|
|
259
|
-
v-else-if="props.modoLayout === 'tabela' && props.idRecursoUnico"
|
|
260
|
-
:id-recurso="props.idRecursoUnico"
|
|
261
|
-
:usa-interceptador="props.usaInterceptador"
|
|
262
|
-
:titulo-padrao="props.tituloPadrao"
|
|
263
|
-
:ocultar-titulo-modal="props.ocultarTituloModal"
|
|
264
|
-
:configuracao-blocos="props.configuracaoBlocos"
|
|
221
|
+
<component
|
|
222
|
+
:is="componenteModeloAtivo"
|
|
223
|
+
ref="modeloAtivoRef"
|
|
224
|
+
v-bind="propriedadesModeloAtivo"
|
|
265
225
|
@before-save="$emit('before-save', $event)"
|
|
266
226
|
>
|
|
267
|
-
<template #
|
|
268
|
-
<slot name="
|
|
227
|
+
<template v-for="(_, nomeSlot) in $slots" :key="nomeSlot" #[nomeSlot]="slotProps">
|
|
228
|
+
<slot :name="nomeSlot" v-bind="slotProps ?? {}"></slot>
|
|
269
229
|
</template>
|
|
270
|
-
</
|
|
271
|
-
|
|
272
|
-
<AgendaMatrix
|
|
273
|
-
v-else-if="props.modoLayout === 'tabela'"
|
|
274
|
-
:usa-interceptador="props.usaInterceptador"
|
|
275
|
-
:titulo-padrao="props.tituloPadrao"
|
|
276
|
-
:ocultar-titulo-modal="props.ocultarTituloModal"
|
|
277
|
-
:configuracao-blocos="props.configuracaoBlocos"
|
|
278
|
-
@before-save="$emit('before-save', $event)"
|
|
279
|
-
>
|
|
280
|
-
<template #campos-extras>
|
|
281
|
-
<slot name="campos-extras"></slot>
|
|
282
|
-
</template>
|
|
283
|
-
</AgendaMatrix>
|
|
230
|
+
</component>
|
|
284
231
|
</main>
|
|
285
232
|
</div>
|
|
286
233
|
</div>
|
|
287
234
|
</div>
|
|
288
235
|
</template>
|
|
236
|
+
|
|
289
237
|
<style lang="scss">
|
|
290
238
|
@use '../assets/scss/main.scss';
|
|
291
239
|
</style>
|
|
292
240
|
|
|
293
241
|
<style scoped>
|
|
294
|
-
.painel-agenda-unificado {
|
|
295
|
-
|
|
296
|
-
border-radius: 16px;
|
|
297
|
-
box-shadow: var(--shadow-float);
|
|
298
|
-
border: 1px solid var(--border-light);
|
|
299
|
-
flex-grow: 1;
|
|
300
|
-
display: flex;
|
|
301
|
-
flex-direction: column;
|
|
302
|
-
overflow: hidden;
|
|
303
|
-
}
|
|
304
|
-
.painel-header-topo {
|
|
305
|
-
height: 60px;
|
|
306
|
-
background-color: var(--bg-primary);
|
|
307
|
-
border-bottom: 1px solid var(--border-light);
|
|
308
|
-
display: flex;
|
|
309
|
-
align-items: center;
|
|
310
|
-
justify-content: space-between;
|
|
311
|
-
padding: 0 20px;
|
|
312
|
-
flex-shrink: 0;
|
|
313
|
-
}
|
|
242
|
+
.painel-agenda-unificado { background: var(--bg-primary); border-radius: 16px; box-shadow: var(--shadow-float); border: 1px solid var(--border-light); flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; }
|
|
243
|
+
.painel-header-topo { height: 60px; background-color: var(--bg-primary); border-bottom: 1px solid var(--border-light); display: flex; align-items: center; justify-content: space-between; padding: 0 20px; flex-shrink: 0; }
|
|
314
244
|
.corpo-principal { display: flex; flex-grow: 1; overflow: hidden; }
|
|
315
|
-
.barra-lateral {
|
|
316
|
-
width: 300px;
|
|
317
|
-
background-color: var(--bg-primary);
|
|
318
|
-
border-right: 1px solid var(--border-light);
|
|
319
|
-
transition: width 0.3s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.2s;
|
|
320
|
-
overflow: hidden;
|
|
321
|
-
flex-shrink: 0;
|
|
322
|
-
}
|
|
245
|
+
.barra-lateral { width: 300px; background-color: var(--bg-primary); border-right: 1px solid var(--border-light); transition: width 0.3s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.2s; overflow: hidden; flex-shrink: 0; }
|
|
323
246
|
.barra-lateral.oculta { width: 0; border-right: none; opacity: 0; }
|
|
324
247
|
.conteudo-lateral-fixo { width: 300px; padding: 15px; }
|
|
325
248
|
.secao-mini-cal { width: 100%; }
|
|
326
|
-
.area-calendario {
|
|
327
|
-
flex-grow: 1;
|
|
328
|
-
overflow: hidden;
|
|
329
|
-
background-color: var(--bg-primary);
|
|
330
|
-
display: flex;
|
|
331
|
-
flex-direction: column;
|
|
332
|
-
}
|
|
333
|
-
|
|
249
|
+
.area-calendario { flex-grow: 1; overflow: hidden; background-color: var(--bg-primary); display: flex; flex-direction: column; }
|
|
334
250
|
.calendario-mini { border: none !important; box-shadow: none !important; background-color: transparent !important; }
|
|
335
|
-
:deep(.calendario-mini .vuecal__header), :deep(.calendario-mini .vuecal__title-bar) { background-color:
|
|
336
|
-
:deep(.calendario-mini .vuecal__title), :deep(.calendario-mini .vuecal__arrow) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
color: var(--color-brand) !important;
|
|
340
|
-
background: transparent !important;
|
|
341
|
-
}
|
|
342
|
-
:deep(.calendario-mini .vuecal__heading) { border: none !important; background-color: transparent !important; font-weight: 600; color: var(--text-secondary); padding-bottom: 4px; }
|
|
251
|
+
:deep(.calendario-mini .vuecal__header), :deep(.calendario-mini .vuecal__title-bar) { background-color: var(--bg-primary) !important; border: none !important; padding-bottom: 5px; }
|
|
252
|
+
:deep(.calendario-mini .vuecal__title), :deep(.calendario-mini .vuecal__arrow) { font-size: 1rem; font-weight: 600; color: var(--color-brand) !important; background: transparent !important; }
|
|
253
|
+
:deep(.calendario-mini .vuecal__weekdays-headings) { background-color: var(--bg-primary) !important; border-bottom: 1px solid var(--border-light) !important; }
|
|
254
|
+
:deep(.calendario-mini .vuecal__heading), :deep(.calendario-mini .vuecal__weekday), :deep(.calendario-mini .vuecal__weekday-name), :deep(.calendario-mini .vuecal__heading *) { background-color: var(--bg-primary) !important; color: var(--text-secondary) !important; font-weight: 600 !important; border: none !important; padding-bottom: 4px; }
|
|
343
255
|
:deep(.calendario-mini .vuecal__cell) { border: none !important; background-color: transparent !important; height: 32px !important; min-height: 32px !important; aspect-ratio: auto !important; }
|
|
344
256
|
:deep(.calendario-mini .vuecal__cell::before) { display: none !important; content: none !important; }
|
|
345
257
|
:deep(.calendario-mini .vuecal__cell-content) { height: 32px !important; min-height: 32px !important; padding: 0 !important; margin: 0 !important; justify-content: center !important; align-items: center !important; width: 100% !important; }
|
|
346
|
-
:deep(.calendario-mini .vuecal__cell-date) { width: 26px !important; height: 26px !important; font-size: 12px !important; line-height: 26px !important; padding: 0 !important; display: flex !important; align-items: center !important; justify-content: center !important; margin: 0 auto !important; border-radius: 50% !important; border: 2px solid transparent !important; box-sizing: border-box !important; transition: all 0.2s ease; cursor: pointer; }
|
|
347
|
-
:deep(.calendario-mini .vuecal__cell--selected) { background-color: transparent !important; }
|
|
348
|
-
:deep(.calendario-mini:not(.modo-mini-tabela-horario) .vuecal__cell--selected .vuecal__cell-date) {
|
|
349
|
-
|
|
350
|
-
color: var(--text-inverse) !important;
|
|
351
|
-
border-color: var(--color-brand) !important;
|
|
352
|
-
}
|
|
258
|
+
:deep(.calendario-mini .vuecal__cell-date) { width: 26px !important; height: 26px !important; font-size: 12px !important; line-height: 26px !important; padding: 0 !important; display: flex !important; align-items: center !important; justify-content: center !important; margin: 0 auto !important; border-radius: 50% !important; border: 2px solid transparent !important; box-sizing: border-box !important; transition: all 0.2s ease; cursor: pointer; background-color: transparent !important; color: var(--text-primary); }
|
|
259
|
+
:deep(.calendario-mini .vuecal__cell--selected), :deep(.calendario-mini .vuecal__cell--today) { background-color: transparent !important; }
|
|
260
|
+
:deep(.calendario-mini:not(.modo-mini-tabela-horario) .vuecal__cell--selected .vuecal__cell-date) { background-color: var(--color-brand) !important; color: var(--text-inverse) !important; border-color: var(--color-brand) !important; }
|
|
261
|
+
:deep(.calendario-mini .vuecal__cell--today:not(.vuecal__cell--selected) .vuecal__cell-date:not(.dia-semana-visivel)) { background-color: var(--color-brand-light) !important; border-color: transparent !important; color: var(--color-brand) !important; }
|
|
353
262
|
:deep(.vuecal__body) { padding: 0; gap: 0; margin: 0; }
|
|
354
|
-
:deep(.calendario-mini .vuecal__cell--today) { background-color: transparent !important; }
|
|
355
|
-
:deep(.calendario-mini .vuecal__cell-date){ background-color: transparent !important; color: var(--text-primary); }
|
|
356
|
-
:deep(.calendario-mini .vuecal__cell--today:not(.vuecal__cell--selected) .vuecal__cell-date:not(.dia-semana-visivel)) {
|
|
357
|
-
background-color: var(--color-brand-light) !important;
|
|
358
|
-
border-color: transparent !important;
|
|
359
|
-
color: var(--color-brand) !important;
|
|
360
|
-
}
|
|
361
263
|
:deep(.calendario-mini .vuecal__views-bar) { display: none !important; }
|
|
362
264
|
:deep(.calendario-mini .vuecal__nav--next), :deep(.calendario-mini .vuecal__nav--prev) { color: var(--text-primary) !important; }
|
|
363
|
-
:deep(.calendario-mini .vuecal__body){ height: 0
|
|
364
|
-
:deep(.calendario-mini .vuecal__scrollable-wrap){ background-color: transparent!important; }
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell--
|
|
368
|
-
pointer-events: none !important;
|
|
369
|
-
cursor: not-allowed !important;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell-date.dia-coluna-inativa) {
|
|
373
|
-
opacity: 0.22 !important;
|
|
374
|
-
color: var(--text-secondary) !important;
|
|
375
|
-
background-color: transparent !important;
|
|
376
|
-
border-color: transparent !important;
|
|
377
|
-
cursor: not-allowed !important;
|
|
378
|
-
pointer-events: none !important;
|
|
379
|
-
text-decoration: line-through;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell-date.dia-semana-visivel) {
|
|
383
|
-
background-color: var(--color-brand) !important;
|
|
384
|
-
color: var(--text-inverse) !important;
|
|
385
|
-
border-color: var(--color-brand) !important;
|
|
386
|
-
font-weight: 700 !important;
|
|
387
|
-
width: 92% !important;
|
|
388
|
-
border-radius: 6px !important;
|
|
389
|
-
cursor: default !important;
|
|
390
|
-
box-shadow: var(--shadow-sm);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
:deep(.calendario-mini .vuecal__weekdays-headings),
|
|
394
|
-
:deep(.calendario-mini .vuecal__weekday) {
|
|
395
|
-
background-color: transparent !important;
|
|
396
|
-
border: none !important;
|
|
397
|
-
color: var(--text-secondary) !important;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
:deep(.calendario-mini .vuecal__weekdays-headings) {
|
|
401
|
-
background: transparent !important;
|
|
402
|
-
background-color: transparent !important;
|
|
403
|
-
border-bottom: 1px solid var(--border-light) !important;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
:deep(.calendario-mini .vuecal__heading),
|
|
407
|
-
:deep(.calendario-mini .vuecal__weekday),
|
|
408
|
-
:deep(.calendario-mini .vuecal__heading *) {
|
|
409
|
-
background: transparent !important;
|
|
410
|
-
background-color: transparent !important;
|
|
411
|
-
color: var(--text-secondary) !important;
|
|
412
|
-
font-weight: 600 !important;
|
|
413
|
-
border: none !important;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
:deep(.calendario-mini .vuecal__header),
|
|
417
|
-
:deep(.calendario-mini .vuecal__weekdays-headings) {
|
|
418
|
-
background: var(--bg-primary) !important;
|
|
419
|
-
background-color: var(--bg-primary) !important;
|
|
420
|
-
border-bottom: 1px solid var(--border-light) !important;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
:deep(.calendario-mini .vuecal__heading),
|
|
424
|
-
:deep(.calendario-mini .vuecal__weekday),
|
|
425
|
-
:deep(.calendario-mini .vuecal__weekday-name),
|
|
426
|
-
:deep(.calendario-mini .vuecal__heading *) {
|
|
427
|
-
background: var(--bg-primary) !important;
|
|
428
|
-
background-color: var(--bg-primary) !important;
|
|
429
|
-
color: var(--text-secondary) !important;
|
|
430
|
-
font-weight: 600 !important;
|
|
431
|
-
border: none !important;
|
|
432
|
-
}
|
|
265
|
+
:deep(.calendario-mini .vuecal__body) { height: 0% !important; }
|
|
266
|
+
:deep(.calendario-mini .vuecal__scrollable-wrap) { background-color: transparent !important; }
|
|
267
|
+
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell--disabled) { pointer-events: none !important; cursor: not-allowed !important; }
|
|
268
|
+
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell-date.dia-coluna-inativa) { opacity: 0.22 !important; color: var(--text-secondary) !important; background-color: transparent !important; border-color: transparent !important; cursor: not-allowed !important; pointer-events: none !important; text-decoration: line-through; }
|
|
269
|
+
:deep(.calendario-mini.modo-mini-tabela-horario .vuecal__cell-date.dia-semana-visivel) { background-color: var(--color-brand) !important; color: var(--text-inverse) !important; border-color: var(--color-brand) !important; font-weight: 700 !important; width: 92% !important; border-radius: 6px !important; cursor: default !important; box-shadow: var(--shadow-sm); }
|
|
433
270
|
</style>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
========
|
|
3
3
|
Este arquivo representa a visualização em matriz para múltiplos recursos com suporte a filtragem.
|
|
4
|
-
Ele utiliza o AgendaMatrixBase para renderizar a grade, repassa a configuração de blocos da agenda
|
|
5
|
-
|
|
4
|
+
Ele utiliza o AgendaMatrixBase para renderizar a grade, repassa a configuração de blocos da agenda,
|
|
5
|
+
gerencia o dropdown de seleção de salas preservando os filtros ativos ao mudar a data e expõe a lista
|
|
6
|
+
de recursos atualmente em exibição (já filtrada).
|
|
6
7
|
========
|
|
7
8
|
-->
|
|
8
9
|
<script setup lang="ts">
|
|
@@ -18,26 +19,18 @@ const props = defineProps({
|
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
const api = inject('api-instance-agenda') as any;
|
|
21
|
-
|
|
22
|
+
defineEmits(['before-save']);
|
|
22
23
|
|
|
23
|
-
const { dadosMatrix, agendaSelecionada } = useAgenda(api);
|
|
24
|
+
const { dadosMatrix, agendaSelecionada, recursosDisponiveis } = useAgenda(api);
|
|
24
25
|
|
|
25
|
-
// Armazena os IDs (em string) dos recursos visíveis selecionados no filtro.
|
|
26
26
|
const recursosVisiveisIds = ref<string[]>([]);
|
|
27
|
-
|
|
28
|
-
// Armazena o ID da última agenda cujo filtro foi inicializado para evitar reset ao mudar apenas a data.
|
|
29
27
|
const idAgendaFiltroInicializado = ref<number | null>(null);
|
|
30
|
-
|
|
31
|
-
// Controla a abertura do menu dropdown de filtro de salas.
|
|
32
28
|
const menuFiltroAberto = ref(false);
|
|
33
29
|
|
|
34
|
-
// Extrai a lista de recursos presentes no primeiro dia retornado na matriz.
|
|
35
30
|
const recursosPermitidosNaMatriz = computed(() => {
|
|
36
|
-
|
|
37
|
-
return dadosMatrix.value.datas_matriz[0].recursos_slot;
|
|
31
|
+
return dadosMatrix.value?.datas_matriz?.[0]?.recursos_slot || [];
|
|
38
32
|
});
|
|
39
33
|
|
|
40
|
-
// Observa os recursos da matriz e inicializa o filtro apenas quando a agenda muda ou na primeira carga.
|
|
41
34
|
watch(recursosPermitidosNaMatriz, (novosRecursos) => {
|
|
42
35
|
if (novosRecursos.length === 0) {
|
|
43
36
|
recursosVisiveisIds.value = [];
|
|
@@ -54,15 +47,31 @@ watch(recursosPermitidosNaMatriz, (novosRecursos) => {
|
|
|
54
47
|
}
|
|
55
48
|
}, { immediate: true });
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
const recursosEmExibicao = computed(() => {
|
|
51
|
+
if (recursosVisiveisIds.value.length === 0) return [];
|
|
52
|
+
|
|
53
|
+
return recursosPermitidosNaMatriz.value
|
|
54
|
+
.filter((recMatriz: any) => recursosVisiveisIds.value.includes(String(recMatriz.id_recurso)))
|
|
55
|
+
.map((recMatriz: any) => {
|
|
56
|
+
return recursosDisponiveis.value.find(
|
|
57
|
+
(r: any) => Number(r.id_recurso) === Number(recMatriz.id_recurso)
|
|
58
|
+
) || {
|
|
59
|
+
id_recurso: recMatriz.id_recurso,
|
|
60
|
+
nome_recurso: recMatriz.nome_recurso,
|
|
61
|
+
id_agenda: agendaSelecionada.value
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
58
66
|
const selecionarTodos = () => {
|
|
59
67
|
recursosVisiveisIds.value = recursosPermitidosNaMatriz.value.map((r: any) => String(r.id_recurso));
|
|
60
68
|
};
|
|
61
69
|
|
|
62
|
-
// Desmarca todos os recursos no filtro de salas.
|
|
63
70
|
const limparFiltros = () => {
|
|
64
71
|
recursosVisiveisIds.value = [];
|
|
65
72
|
};
|
|
73
|
+
|
|
74
|
+
defineExpose({ recursosEmExibicao });
|
|
66
75
|
</script>
|
|
67
76
|
|
|
68
77
|
<template>
|
|
@@ -73,7 +82,7 @@ const limparFiltros = () => {
|
|
|
73
82
|
:ocultar-titulo-modal="props.ocultarTituloModal"
|
|
74
83
|
:configuracao-blocos="props.configuracaoBlocos"
|
|
75
84
|
mensagem-vazio="Nenhuma sala selecionada."
|
|
76
|
-
@before-save="$emit('before-save'
|
|
85
|
+
@before-save="$emit('before-save',$event)"
|
|
77
86
|
>
|
|
78
87
|
<template #topo>
|
|
79
88
|
<div class="barra-filtros" v-if="recursosPermitidosNaMatriz.length > 0">
|
|
@@ -125,8 +134,8 @@ const limparFiltros = () => {
|
|
|
125
134
|
</div>
|
|
126
135
|
</template>
|
|
127
136
|
|
|
128
|
-
<template #
|
|
129
|
-
<slot name="
|
|
137
|
+
<template v-for="(_, nomeSlot) in $slots" :key="nomeSlot" #[nomeSlot]="slotProps">
|
|
138
|
+
<slot :name="nomeSlot" v-bind="slotProps ?? {}"></slot>
|
|
130
139
|
</template>
|
|
131
140
|
</AgendaMatrixBase>
|
|
132
141
|
</template>
|