v-sistec-features 1.31.13 → 1.32.0

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 (152) hide show
  1. package/dist/DataAgenda/VDataAgenda.vue.d.ts +915 -0
  2. package/dist/DataAgenda/components/AgendaMatrix.vue.d.ts +64 -0
  3. package/dist/DataAgenda/components/AgendaMatrixBase.vue.d.ts +31 -0
  4. package/dist/DataAgenda/components/AgendaMatrixUnico.vue.d.ts +72 -0
  5. package/dist/DataAgenda/components/AgendaTabelaHorario.vue.d.ts +32 -0
  6. package/dist/DataAgenda/components/AgendaVueCal.vue.d.ts +94 -0
  7. package/dist/DataAgenda/components/BlocoArrastavel.vue.d.ts +37 -0
  8. package/dist/DataAgenda/components/HeaderCalendario.vue.d.ts +7 -0
  9. package/dist/DataAgenda/components/HeaderTabela.vue.d.ts +7 -0
  10. package/dist/DataAgenda/components/ModalDetalhesReserva.vue.d.ts +38 -0
  11. package/dist/DataAgenda/components/ModalReserva.vue.d.ts +157 -0
  12. package/dist/DataAgenda/composables/useAgenda.d.ts +24 -0
  13. package/dist/DataAgenda/composables/useCoresAgenda.d.ts +7 -0
  14. package/dist/DataAgenda/composables/useGradeCompartilhada.d.ts +23 -0
  15. package/dist/DataAgenda/composables/useSelecaoArrasto.d.ts +24 -0
  16. package/dist/DataAgenda/index.d.ts +2 -0
  17. package/dist/DataPageVue/components/VDataPage.vue.d.ts +50 -0
  18. package/dist/DataPageVue/index.d.ts +2 -0
  19. package/dist/DataPageVue/types/v-data-page.d.ts +53 -0
  20. package/dist/DatatableVue/components/SearchDatatable.vue.d.ts +28 -0
  21. package/dist/DatatableVue/components/VColumn.vue.d.ts +82 -0
  22. package/dist/DatatableVue/components/VColumnManager.vue.d.ts +21 -0
  23. package/dist/DatatableVue/components/VDataTable.vue.d.ts +57 -0
  24. package/dist/DatatableVue/components/VDataTableLoading.vue.d.ts +17 -0
  25. package/dist/DatatableVue/components/VOrderingIcon.vue.d.ts +10 -0
  26. package/dist/DatatableVue/components/VThDataTable.vue.d.ts +14 -0
  27. package/dist/DatatableVue/composables/useCheckBox.d.ts +11 -0
  28. package/dist/DatatableVue/composables/useDataTableConfig.d.ts +4 -0
  29. package/dist/DatatableVue/composables/useDataTableFetch.d.ts +17 -0
  30. package/dist/DatatableVue/composables/useExpandedItem.d.ts +6 -0
  31. package/dist/DatatableVue/composables/useImagePreview.d.ts +9 -0
  32. package/dist/DatatableVue/config/datatableConfig.d.ts +4 -0
  33. package/dist/DatatableVue/config/datatableDefaults.d.ts +7 -0
  34. package/dist/DatatableVue/index.d.ts +3 -0
  35. package/dist/DatatableVue/keys.d.ts +39 -0
  36. package/dist/DatatableVue/style/svgs.d.ts +20 -0
  37. package/dist/DatatableVue/types/v-data-table.d.ts +161 -0
  38. package/dist/Modals/components/BotaoFechar.vue.d.ts +36 -0
  39. package/dist/Modals/components/ModalAviso.vue.d.ts +184 -0
  40. package/dist/Modals/components/ModalBaseDefault.vue.d.ts +244 -0
  41. package/dist/Modals/components/ModalConfirmacao.vue.d.ts +184 -0
  42. package/dist/Modals/components/ModalConfirmacaoCheckbox.vue.d.ts +195 -0
  43. package/dist/Modals/components/ModalConfirmacaoInput.vue.d.ts +238 -0
  44. package/dist/Modals/components/ModalConfirmacaoSimples.vue.d.ts +187 -0
  45. package/dist/Modals/components/ModalInformacao.vue.d.ts +184 -0
  46. package/dist/Modals/components/ModalPerigo.vue.d.ts +175 -0
  47. package/dist/Modals/components/ModalSucesso.vue.d.ts +175 -0
  48. package/dist/Modals/components/interno/ModalDialogoInterno.vue.d.ts +205 -0
  49. package/dist/Modals/index.d.ts +12 -0
  50. package/dist/Modals.js +1361 -0
  51. package/dist/Pagination/Pagination.vue.d.ts +19 -0
  52. package/dist/Pagination/index.d.ts +2 -0
  53. package/dist/{Pagination-f4FVE5TX.js → Pagination-D96eBRod.js} +25 -25
  54. package/dist/Pagination.js +1 -1
  55. package/dist/{ar-Bg_10XBG.js → ar-CtSPmWrk.js} +0 -5
  56. package/dist/{bg-DyIRbFaU.js → bg-DwW4tkzm.js} +0 -5
  57. package/dist/{bn-DrKXkRvN.js → bn-Df__ccyH.js} +0 -5
  58. package/dist/{bs-BF8upphm.js → bs-j17x02qr.js} +0 -5
  59. package/dist/{ca-CGMnsdII.js → ca-B94lUx7c.js} +0 -5
  60. package/dist/core/index.d.ts +1 -0
  61. package/dist/core/plugin.d.ts +11 -0
  62. package/dist/core.js +1 -1
  63. package/dist/{cs-B-jeNB5o.js → cs-DeDzN7tG.js} +0 -5
  64. package/dist/{da-BoHemyXx.js → da-DMpC5y8O.js} +0 -5
  65. package/dist/datatableConfig-E5_08Ch4.js +4 -0
  66. package/dist/{de-DNAaiTrc.js → de-CCNUZSup.js} +0 -5
  67. package/dist/{el-Cpg3pI7i.js → el-C2kkX76k.js} +0 -5
  68. package/dist/{en-gb-KsKdvLmV.js → en-gb-sbYhvlrM.js} +0 -5
  69. package/dist/{es-COziTcsp.js → es-mNgFJGue.js} +0 -5
  70. package/dist/{et-BdTtu9t_.js → et-D0ro6m_Z.js} +0 -5
  71. package/dist/{fa-B1Ebp36t.js → fa-DYekHC6-.js} +0 -5
  72. package/dist/{fi-b4XodxNE.js → fi-CNexLCO_.js} +0 -5
  73. package/dist/{fr-BIx4sO6s.js → fr-CUXtdWLj.js} +0 -5
  74. package/dist/{he-rf_Y5d64.js → he-D4BblsAD.js} +0 -5
  75. package/dist/{hr-DOuJJGF3.js → hr-1MNJjxDo.js} +0 -5
  76. package/dist/{hu-DMc8kv_1.js → hu-BiG8mSvH.js} +0 -5
  77. package/dist/{id-DclBfDY0.js → id-CABEuSQB.js} +0 -5
  78. package/dist/iframeCommunicator/index.d.ts +2 -0
  79. package/dist/iframeCommunicator/useIframeCommunicator.d.ts +8 -0
  80. package/dist/iframeCommunicator/useThemeFromParent.d.ts +9 -0
  81. package/dist/index.d.ts +3 -140
  82. package/dist/index.js +1 -1
  83. package/dist/{is-hPcr999q.js → is-DBUkoxb1.js} +0 -5
  84. package/dist/{it-Dfz57Ogc.js → it-Am_Oo5d5.js} +0 -5
  85. package/dist/{ja-Da6Dbgu8.js → ja-C4aaunra.js} +0 -5
  86. package/dist/{ka-DK-BKZD4.js → ka-CkzS4fNj.js} +0 -5
  87. package/dist/{kaa-BVd8dKz3.js → kaa-GTw11GU-.js} +0 -5
  88. package/dist/{kk-eE3-SI4R.js → kk-BRFq2Ctd.js} +0 -5
  89. package/dist/{ko-CUMtwCHy.js → ko-BbgS6BMk.js} +0 -5
  90. package/dist/{ky-CCU0MYbD.js → ky-ClK6HL0m.js} +0 -5
  91. package/dist/{lt-CpbQmiiW.js → lt-BE0ahgri.js} +0 -5
  92. package/dist/{mn-YYwo93uK.js → mn-C-Ktk8ht.js} +0 -5
  93. package/dist/{nl-WqtgByJL.js → nl-BiG9OH1y.js} +0 -5
  94. package/dist/{no-BOG8-aOm.js → no-DVdX7xTS.js} +0 -5
  95. package/dist/{pl-BH4AyCMF.js → pl-y_N8wVAF.js} +0 -5
  96. package/dist/plugin-BZB7f-c3.js +3444 -0
  97. package/dist/{pt-br-siyrXjdv.js → pt-br-Cx8Akpcu.js} +0 -5
  98. package/dist/{pt-pt-siyrXjdv.js → pt-pt-Cx8Akpcu.js} +0 -5
  99. package/dist/{ro-C9fU41Qi.js → ro-FfAZHwo1.js} +0 -5
  100. package/dist/{ru-_d_rl3a5.js → ru-BCE9k5uo.js} +0 -5
  101. package/dist/{sk-ZT421l3d.js → sk-D-7bEf3b.js} +0 -5
  102. package/dist/{sl-Ct8Gi5v1.js → sl-DoVrM4Ht.js} +0 -5
  103. package/dist/{sq-Cw7PWK-V.js → sq-Du8jVeq7.js} +0 -5
  104. package/dist/{sr-DO-S1wn3.js → sr-DP3yke6-.js} +0 -5
  105. package/dist/{sv-NXMCPui2.js → sv-C2iGWFqL.js} +0 -5
  106. package/dist/toast/components/ToastComponent.vue.d.ts +6 -0
  107. package/dist/toast/index.d.ts +1 -0
  108. package/dist/toast/useToastStore.d.ts +11 -0
  109. package/dist/toast.js +2 -2
  110. package/dist/{tr-BpieMIth.js → tr-CvlANdCR.js} +0 -5
  111. package/dist/{uk-CqVU4EoZ.js → uk-CxFb8w2s.js} +0 -5
  112. package/dist/utils/svgFactory.d.ts +8 -0
  113. package/dist/{uz-CmcB22-w.js → uz-DmJPqTjK.js} +0 -5
  114. package/dist/{uz-cryl-C_GBVdXl.js → uz-cryl-Dt065WNc.js} +0 -5
  115. package/dist/v-sistec-features.css +1 -11
  116. package/dist/vDataAgenda.js +1877 -1885
  117. package/dist/vDataPage.js +31 -41
  118. package/dist/vDataTable.js +43 -43
  119. package/dist/{vi-C9wTd3fG.js → vi-B8R5Ozvj.js} +0 -5
  120. package/dist/{zh-cn-DY7nkJwf.js → zh-cn-DnUuIcqx.js} +0 -5
  121. package/dist/{zh-hk-KkazoDdS.js → zh-hk-mDkIkhi9.js} +0 -5
  122. package/package.json +5 -1
  123. package/src/DataAgenda/VDataAgenda.vue +233 -77
  124. package/src/DataAgenda/components/AgendaMatrix.vue +1 -0
  125. package/src/DataAgenda/components/AgendaMatrixBase.vue +357 -140
  126. package/src/DataAgenda/components/AgendaMatrixUnico.vue +1 -0
  127. package/src/DataAgenda/components/AgendaTabelaHorario.vue +489 -316
  128. package/src/DataAgenda/components/AgendaVueCal.vue +1 -0
  129. package/src/DataAgenda/index.ts +2 -1
  130. package/src/Modals/components/BotaoFechar.vue +74 -0
  131. package/src/Modals/components/ModalAviso.vue +129 -0
  132. package/src/Modals/components/ModalBaseDefault.vue +374 -0
  133. package/src/Modals/components/ModalConfirmacao.vue +129 -0
  134. package/src/Modals/components/ModalConfirmacaoCheckbox.vue +155 -0
  135. package/src/Modals/components/ModalConfirmacaoInput.vue +200 -0
  136. package/src/Modals/components/ModalConfirmacaoSimples.vue +306 -0
  137. package/src/Modals/components/ModalInformacao.vue +129 -0
  138. package/src/Modals/components/ModalPerigo.vue +123 -0
  139. package/src/Modals/components/ModalSucesso.vue +123 -0
  140. package/src/Modals/components/interno/ModalDialogoInterno.vue +365 -0
  141. package/src/Modals/index.ts +32 -0
  142. package/src/core/plugin.ts +34 -41
  143. package/src/types/global.d.ts +7 -1
  144. package/dist/Pagination.d.ts +0 -27
  145. package/dist/core.d.ts +0 -117
  146. package/dist/datatableConfig-BMFlKtgh.js +0 -4
  147. package/dist/iframeCommunicator.d.ts +0 -22
  148. package/dist/plugin-BwqrOSD_.js +0 -2097
  149. package/dist/toast.d.ts +0 -19
  150. package/dist/vDataAgenda.d.ts +0 -929
  151. package/dist/vDataPage.d.ts +0 -117
  152. package/dist/vDataTable.d.ts +0 -294
@@ -7,42 +7,43 @@ e exposição da lista contendo o recurso atualmente em exibição.
7
7
  ========
8
8
  -->
9
9
  <script setup lang="ts">
10
+ defineSlots<{ [key: string]: any }>();
10
11
  import { computed, watch, inject } from 'vue';
11
12
  import { useAgenda } from '../composables/useAgenda';
12
13
  import { useCoresAgenda } from '../composables/useCoresAgenda';
13
14
  import { useSelecaoArrasto } from '../composables/useSelecaoArrasto';
14
15
  import {
15
- SIGLAS_DIAS_JS,
16
- TITULOS_DIAS_CABECALHO,
17
- extrairDataHoraLocal,
18
- extrairHoraFormatada,
19
- criarDataLocal,
20
- mesclarSlotsReservados,
21
- useGradeSemanal,
22
- useSincronizarRecursoUnico
16
+ SIGLAS_DIAS_JS,
17
+ TITULOS_DIAS_CABECALHO,
18
+ extrairDataHoraLocal,
19
+ extrairHoraFormatada,
20
+ criarDataLocal,
21
+ mesclarSlotsReservados,
22
+ useGradeSemanal,
23
+ useSincronizarRecursoUnico
23
24
  } from '../composables/useGradeCompartilhada';
24
25
  import BlocoArrastavel from './BlocoArrastavel.vue';
25
26
  import ModalReserva from './ModalReserva.vue';
26
27
  import ModalDetalhesReserva from './ModalDetalhesReserva.vue';
27
28
 
28
29
  interface MetadadoLinha {
29
- horaInicio: string;
30
- horaFim: string;
31
- corFundo: string;
32
- corBorda: string;
33
- mostrarBlocoLateral: boolean;
34
- nomeBlocoLateral: string;
35
- rowspanBlocoLateral: number;
36
- fimDeSubbloco: boolean;
37
- fimDeBlocoPrincipal: boolean;
30
+ horaInicio: string;
31
+ horaFim: string;
32
+ corFundo: string;
33
+ corBorda: string;
34
+ mostrarBlocoLateral: boolean;
35
+ nomeBlocoLateral: string;
36
+ rowspanBlocoLateral: number;
37
+ fimDeSubbloco: boolean;
38
+ fimDeBlocoPrincipal: boolean;
38
39
  }
39
40
 
40
41
  const props = defineProps<{
41
- idRecursoUnico?: number | string | null;
42
- usaInterceptador?: boolean;
43
- tituloPadrao?: string;
44
- ocultarTituloModal?: boolean;
45
- configuracaoBlocos?: any;
42
+ idRecursoUnico?: number | string | null;
43
+ usaInterceptador?: boolean;
44
+ tituloPadrao?: string;
45
+ ocultarTituloModal?: boolean;
46
+ configuracaoBlocos?: any;
46
47
  }>();
47
48
 
48
49
  const api = inject('api-instance-agenda') as any;
@@ -54,266 +55,257 @@ const { theme, obterCoresBloco } = useCoresAgenda();
54
55
  useSincronizarRecursoUnico(api, () => props.idRecursoUnico);
55
56
 
56
57
  const {
57
- dadosMatrix,
58
- carregando,
59
- modalAberto,
60
- dadosParaModal,
61
- modalDetalhesAberto,
62
- reservaSelecionadaDetalhes,
63
- obterBlocosDoDia,
64
- dispararBuscaSemanal
58
+ dadosMatrix,
59
+ carregando,
60
+ modalAberto,
61
+ dadosParaModal,
62
+ modalDetalhesAberto,
63
+ reservaSelecionadaDetalhes,
64
+ obterBlocosDoDia,
65
+ dispararBuscaSemanal
65
66
  } = useGradeSemanal(api, () => props.configuracaoBlocos);
66
67
 
67
68
  // Quando a agenda muda no seletor e não há idRecursoUnico fixo, garante que o recursoSelecionado pertença à agenda ativa.
68
69
  watch(agendaSelecionada, (novoIdAgenda) => {
69
- if (!novoIdAgenda || props.idRecursoUnico) return;
70
- const pertence = recursosDisponiveis.value.some(
71
- (r: any) => Number(r.id_recurso) === Number(recursoSelecionado.value) && Number(r.id_agenda) === Number(novoIdAgenda)
70
+ if (!novoIdAgenda || props.idRecursoUnico) return;
71
+ const pertence = recursosDisponiveis.value.some(
72
+ (r: any) => Number(r.id_recurso) === Number(recursoSelecionado.value) && Number(r.id_agenda) === Number(novoIdAgenda)
73
+ );
74
+ if (!pertence) {
75
+ const primeiroDaAgenda = recursosDisponiveis.value.find(
76
+ (r: any) => Number(r.id_agenda) === Number(novoIdAgenda)
72
77
  );
73
- if (!pertence) {
74
- const primeiroDaAgenda = recursosDisponiveis.value.find(
75
- (r: any) => Number(r.id_agenda) === Number(novoIdAgenda)
76
- );
77
- if (primeiroDaAgenda) {
78
- recursoSelecionado.value = Number(primeiroDaAgenda.id_recurso);
79
- }
78
+ if (primeiroDaAgenda) {
79
+ recursoSelecionado.value = Number(primeiroDaAgenda.id_recurso);
80
80
  }
81
+ }
81
82
  });
82
83
 
83
84
  const recursosDaAgendaAtual = computed(() => {
84
- if (!agendaSelecionada.value) return recursosDisponiveis.value;
85
- return recursosDisponiveis.value.filter(
86
- (r: any) => Number(r.id_agenda) === Number(agendaSelecionada.value)
87
- );
85
+ if (!agendaSelecionada.value) return recursosDisponiveis.value;
86
+ return recursosDisponiveis.value.filter(
87
+ (r: any) => Number(r.id_agenda) === Number(agendaSelecionada.value)
88
+ );
88
89
  });
89
90
 
90
91
  const idRecursoAtivo = computed(() => {
91
- if (props.idRecursoUnico) return Number(props.idRecursoUnico);
92
- if (recursoSelecionado.value) return Number(recursoSelecionado.value);
93
- const primeiro = recursosDaAgendaAtual.value[0];
94
- return primeiro ? Number(primeiro.id_recurso) : null;
92
+ if (props.idRecursoUnico) return Number(props.idRecursoUnico);
93
+ if (recursoSelecionado.value) return Number(recursoSelecionado.value);
94
+ const primeiro = recursosDaAgendaAtual.value[0];
95
+ return primeiro ? Number(primeiro.id_recurso) : null;
95
96
  });
96
97
 
97
98
  const recursosEmExibicao = computed(() => {
98
- if (!idRecursoAtivo.value) return [];
99
- const encontrado = recursosDisponiveis.value.find(
100
- (r: any) => Number(r.id_recurso) === Number(idRecursoAtivo.value)
101
- );
102
- return encontrado ? [encontrado] : [];
99
+ if (!idRecursoAtivo.value) return [];
100
+ const encontrado = recursosDisponiveis.value.find(
101
+ (r: any) => Number(r.id_recurso) === Number(idRecursoAtivo.value)
102
+ );
103
+ return encontrado ? [encontrado] : [];
103
104
  });
104
105
 
105
106
  defineExpose({ recursosEmExibicao });
106
107
 
107
108
  const controladorArrastoVertical = useSelecaoArrasto({
108
- aoClicarItemIndisponivel: (celula) => {
109
- if (celula?.reservado_slot && celula?.detalhes_reserva) {
110
- reservaSelecionadaDetalhes.value = celula.detalhes_reserva;
111
- modalDetalhesAberto.value = true;
112
- }
113
- },
114
- aoFinalizarSelecao: ({ itensSelecionados }) => {
115
- if (!idRecursoAtivo.value) return;
116
- const slotInicial = itensSelecionados[0];
117
- const slotFinal = itensSelecionados[itensSelecionados.length - 1];
118
- if (!slotInicial || !slotFinal) return;
119
-
120
- const inicio = extrairDataHoraLocal(slotInicial.data_inicio_slot);
121
- const fim = extrairDataHoraLocal(slotFinal.data_fim_slot);
122
-
123
- dadosParaModal.value = {
124
- id_recurso: idRecursoAtivo.value,
125
- titulo_reserva: '',
126
- data_inicio: inicio.data,
127
- hora_inicio: inicio.hora,
128
- data_fim: fim.data,
129
- hora_fim: fim.hora
130
- };
131
-
132
- modalAberto.value = true;
109
+ aoClicarItemIndisponivel: (celula) => {
110
+ if (celula?.reservado_slot && celula?.detalhes_reserva) {
111
+ reservaSelecionadaDetalhes.value = celula.detalhes_reserva;
112
+ modalDetalhesAberto.value = true;
133
113
  }
114
+ },
115
+ aoFinalizarSelecao: ({ itensSelecionados }) => {
116
+ if (!idRecursoAtivo.value) return;
117
+ const slotInicial = itensSelecionados[0];
118
+ const slotFinal = itensSelecionados[itensSelecionados.length - 1];
119
+ if (!slotInicial || !slotFinal) return;
120
+
121
+ const inicio = extrairDataHoraLocal(slotInicial.data_inicio_slot);
122
+ const fim = extrairDataHoraLocal(slotFinal.data_fim_slot);
123
+
124
+ dadosParaModal.value = {
125
+ id_recurso: idRecursoAtivo.value,
126
+ titulo_reserva: '',
127
+ data_inicio: inicio.data,
128
+ hora_inicio: inicio.hora,
129
+ data_fim: fim.data,
130
+ hora_fim: fim.hora
131
+ };
132
+
133
+ modalAberto.value = true;
134
+ }
134
135
  });
135
136
 
136
137
  // Processa a lista de horários de um grupo de dias e gera os metadados de cada linha (bloco lateral, cor e bordas de subdivisão).
137
138
  const mapearLinhasComBlocos = (horariosBase: { horaInicio: string; horaFim: string }[], siglaDia: string) => {
138
- const total = horariosBase.length;
139
- const listaBlocos = obterBlocosDoDia(siglaDia);
140
-
141
- const metadadosLinhas: MetadadoLinha[] = horariosBase.map((h) => ({
142
- horaInicio: h.horaInicio,
143
- horaFim: h.horaFim,
144
- corFundo: theme.value === 'dark' ? 'var(--bg-primary)' : '#FFFFFF',
145
- corBorda: 'var(--border-light)',
146
- mostrarBlocoLateral: false,
147
- nomeBlocoLateral: '',
148
- rowspanBlocoLateral: 1,
149
- fimDeSubbloco: false,
150
- fimDeBlocoPrincipal: false
151
- }));
139
+ const total = horariosBase.length;
140
+ const listaBlocos = obterBlocosDoDia(siglaDia);
141
+
142
+ const metadadosLinhas: MetadadoLinha[] = horariosBase.map((h) => ({
143
+ horaInicio: h.horaInicio,
144
+ horaFim: h.horaFim,
145
+ corFundo: theme.value === 'dark' ? 'var(--bg-primary)' : '#FFFFFF',
146
+ corBorda: 'var(--border-light)',
147
+ mostrarBlocoLateral: false,
148
+ nomeBlocoLateral: '',
149
+ rowspanBlocoLateral: 1,
150
+ fimDeSubbloco: false,
151
+ fimDeBlocoPrincipal: false
152
+ }));
153
+
154
+ if (!listaBlocos || listaBlocos.length === 0) {
155
+ return { temColunaTurno: false, linhas: metadadosLinhas };
156
+ }
157
+
158
+ let cursor = 0;
159
+
160
+ listaBlocos.forEach((blocoCfg: any, idxBloco: number) => {
161
+ if (cursor >= total) return;
162
+ const qtdSolicitada = Number(blocoCfg.quantidade) || 0;
163
+ const qtdReal = Math.min(qtdSolicitada, total - cursor);
164
+ if (qtdReal <= 0) return;
165
+
166
+ const { corFundo, corBorda } = obterCoresBloco(idxBloco);
167
+
168
+ const metaCursor = metadadosLinhas[cursor];
169
+ if (metaCursor) {
170
+ metaCursor.mostrarBlocoLateral = true;
171
+ metaCursor.nomeBlocoLateral = blocoCfg.nome || `TURNO ${idxBloco + 1}`;
172
+ metaCursor.rowspanBlocoLateral = qtdReal;
173
+ }
152
174
 
153
- if (!listaBlocos || listaBlocos.length === 0) {
154
- return { temColunaTurno: false, linhas: metadadosLinhas };
175
+ for (let i = 0; i < qtdReal; i++) {
176
+ const metaItem = metadadosLinhas[cursor + i];
177
+ if (metaItem) {
178
+ metaItem.corFundo = corFundo;
179
+ metaItem.corBorda = corBorda;
180
+ }
155
181
  }
156
182
 
157
- let cursor = 0;
158
-
159
- listaBlocos.forEach((blocoCfg: any, idxBloco: number) => {
160
- if (cursor >= total) return;
161
- const qtdSolicitada = Number(blocoCfg.quantidade) || 0;
162
- const qtdReal = Math.min(qtdSolicitada, total - cursor);
163
- if (qtdReal <= 0) return;
164
-
165
- const { corFundo, corBorda } = obterCoresBloco(idxBloco);
166
-
167
- const metaCursor = metadadosLinhas[cursor];
168
- if (metaCursor) {
169
- metaCursor.mostrarBlocoLateral = true;
170
- metaCursor.nomeBlocoLateral = blocoCfg.nome || `TURNO ${idxBloco + 1}`;
171
- metaCursor.rowspanBlocoLateral = qtdReal;
172
- }
173
-
174
- for (let i = 0; i < qtdReal; i++) {
175
- const metaItem = metadadosLinhas[cursor + i];
176
- if (metaItem) {
177
- metaItem.corFundo = corFundo;
178
- metaItem.corBorda = corBorda;
179
- }
180
- }
181
-
182
- const subFixo = Number(blocoCfg.subdivisao) || 0;
183
- const subLista = Array.isArray(blocoCfg.subdivisoes) ? blocoCfg.subdivisoes : null;
184
-
185
- if (subLista && subLista.length > 0) {
186
- let consumido = 0;
187
- subLista.forEach((tam: number) => {
188
- if (consumido >= qtdReal) return;
189
- consumido += Math.min(Number(tam) || 1, qtdReal - consumido);
190
- const metaFimSub = metadadosLinhas[cursor + consumido - 1];
191
- if (metaFimSub) metaFimSub.fimDeSubbloco = true;
192
- });
193
- } else if (subFixo > 0) {
194
- let consumido = 0;
195
- while (consumido < qtdReal) {
196
- consumido += Math.min(subFixo, qtdReal - consumido);
197
- const metaFimSub = metadadosLinhas[cursor + consumido - 1];
198
- if (metaFimSub) metaFimSub.fimDeSubbloco = true;
199
- }
200
- }
201
-
202
- const metaFimPrincipal = metadadosLinhas[cursor + qtdReal - 1];
203
- if (metaFimPrincipal) metaFimPrincipal.fimDeBlocoPrincipal = true;
204
- cursor += qtdReal;
205
- });
183
+ const subFixo = Number(blocoCfg.subdivisao) || 0;
184
+ const subLista = Array.isArray(blocoCfg.subdivisoes) ? blocoCfg.subdivisoes : null;
185
+
186
+ if (subLista && subLista.length > 0) {
187
+ let consumido = 0;
188
+ subLista.forEach((tam: number) => {
189
+ if (consumido >= qtdReal) return;
190
+ consumido += Math.min(Number(tam) || 1, qtdReal - consumido);
191
+ const metaFimSub = metadadosLinhas[cursor + consumido - 1];
192
+ if (metaFimSub) metaFimSub.fimDeSubbloco = true;
193
+ });
194
+ } else if (subFixo > 0) {
195
+ let consumido = 0;
196
+ while (consumido < qtdReal) {
197
+ consumido += Math.min(subFixo, qtdReal - consumido);
198
+ const metaFimSub = metadadosLinhas[cursor + consumido - 1];
199
+ if (metaFimSub) metaFimSub.fimDeSubbloco = true;
200
+ }
201
+ }
202
+
203
+ const metaFimPrincipal = metadadosLinhas[cursor + qtdReal - 1];
204
+ if (metaFimPrincipal) metaFimPrincipal.fimDeBlocoPrincipal = true;
205
+ cursor += qtdReal;
206
+ });
206
207
 
207
- if (cursor < total) {
208
- const restante = total - cursor;
209
- const { corFundo, corBorda } = obterCoresBloco(listaBlocos.length);
210
-
211
- const metaRestante = metadadosLinhas[cursor];
212
- if (metaRestante) {
213
- metaRestante.mostrarBlocoLateral = true;
214
- metaRestante.nomeBlocoLateral = 'OUTROS';
215
- metaRestante.rowspanBlocoLateral = restante;
216
- }
217
-
218
- for (let i = 0; i < restante; i++) {
219
- const metaItem = metadadosLinhas[cursor + i];
220
- if (metaItem) {
221
- metaItem.corFundo = corFundo;
222
- metaItem.corBorda = corBorda;
223
- }
224
- }
225
-
226
- const metaUltimo = metadadosLinhas[total - 1];
227
- if (metaUltimo) metaUltimo.fimDeBlocoPrincipal = true;
208
+ if (cursor < total) {
209
+ const restante = total - cursor;
210
+ const { corFundo, corBorda } = obterCoresBloco(listaBlocos.length);
211
+
212
+ const metaRestante = metadadosLinhas[cursor];
213
+ if (metaRestante) {
214
+ metaRestante.mostrarBlocoLateral = true;
215
+ metaRestante.nomeBlocoLateral = 'OUTROS';
216
+ metaRestante.rowspanBlocoLateral = restante;
228
217
  }
229
218
 
230
- return { temColunaTurno: true, linhas: metadadosLinhas };
219
+ for (let i = 0; i < restante; i++) {
220
+ const metaItem = metadadosLinhas[cursor + i];
221
+ if (metaItem) {
222
+ metaItem.corFundo = corFundo;
223
+ metaItem.corBorda = corBorda;
224
+ }
225
+ }
226
+
227
+ const metaUltimo = metadadosLinhas[total - 1];
228
+ if (metaUltimo) metaUltimo.fimDeBlocoPrincipal = true;
229
+ }
230
+
231
+ return { temColunaTurno: true, linhas: metadadosLinhas };
231
232
  };
232
233
 
233
234
  // Constrói a estrutura completa de grupos de colunas e calcula o rowspan das reservas.
234
235
  const estruturaGradeHorario = computed(() => {
235
- if (!dadosMatrix.value?.datas_matriz || !idRecursoAtivo.value) {
236
- return { grupos: [], maxLinhas: 0, temColunaTurnoPrincipal: false };
237
- }
236
+ if (!dadosMatrix.value?.datas_matriz || !idRecursoAtivo.value) {
237
+ return { grupos: [], maxLinhas: 0, temColunaTurnoPrincipal: false };
238
+ }
239
+
240
+ const diasOperacionais = dadosMatrix.value.datas_matriz.filter(
241
+ (d: any) => d.dia_operacional_slot !== false
242
+ );
243
+
244
+ const gruposPorAssinatura = new Map<string, any>();
238
245
 
239
- const diasOperacionais = dadosMatrix.value.datas_matriz.filter(
240
- (d: any) => d.dia_operacional_slot !== false
246
+ diasOperacionais.forEach((dia: any) => {
247
+ const recObj = (dia.recursos_slot || []).find(
248
+ (r: any) => Number(r.id_recurso) === Number(idRecursoAtivo.value)
241
249
  );
250
+ if (!recObj) return;
251
+
252
+ const slotsReservaveis = (recObj.horarios_slot || []).filter((s: any) => !s.bloqueado_slot);
253
+ if (slotsReservaveis.length === 0) return;
254
+
255
+ const horariosDia = slotsReservaveis.map((s: any) => ({
256
+ horaInicio: extrairHoraFormatada(s.data_inicio_slot),
257
+ horaFim: extrairHoraFormatada(s.data_fim_slot)
258
+ }));
259
+
260
+ const assinatura = horariosDia.map((h: any) => `${h.horaInicio}-${h.horaFim}`).join('|');
261
+ const dtLocal = criarDataLocal(dia.data_slot);
262
+ const siglaDia = SIGLAS_DIAS_JS[dtLocal.getDay()] || 'SEG';
263
+ const tituloDia = TITULOS_DIAS_CABECALHO[dtLocal.getDay()] || siglaDia;
264
+ const dataCurta = dtLocal.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' });
265
+
266
+ if (!gruposPorAssinatura.has(assinatura)) {
267
+ const infoLinhas = mapearLinhasComBlocos(horariosDia, siglaDia);
268
+ gruposPorAssinatura.set(assinatura, {
269
+ assinatura,
270
+ siglaReferencia: siglaDia,
271
+ temColunaTurno: infoLinhas.temColunaTurno,
272
+ linhasMetadados: infoLinhas.linhas,
273
+ dias: []
274
+ });
275
+ }
242
276
 
243
- const gruposPorAssinatura = new Map<string, any>();
244
-
245
- diasOperacionais.forEach((dia: any) => {
246
- const recObj = (dia.recursos_slot || []).find(
247
- (r: any) => Number(r.id_recurso) === Number(idRecursoAtivo.value)
248
- );
249
- if (!recObj) return;
250
-
251
- const slotsReservaveis = (recObj.horarios_slot || []).filter((s: any) => !s.bloqueado_slot);
252
- if (slotsReservaveis.length === 0) return;
253
-
254
- const horariosDia = slotsReservaveis.map((s: any) => ({
255
- horaInicio: extrairHoraFormatada(s.data_inicio_slot),
256
- horaFim: extrairHoraFormatada(s.data_fim_slot)
257
- }));
258
-
259
- const assinatura = horariosDia.map((h: any) => `${h.horaInicio}-${h.horaFim}`).join('|');
260
- const dtLocal = criarDataLocal(dia.data_slot);
261
- const siglaDia = SIGLAS_DIAS_JS[dtLocal.getDay()] || 'SEG';
262
- const tituloDia = TITULOS_DIAS_CABECALHO[dtLocal.getDay()] || siglaDia;
263
- const dataCurta = dtLocal.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' });
264
-
265
- if (!gruposPorAssinatura.has(assinatura)) {
266
- const infoLinhas = mapearLinhasComBlocos(horariosDia, siglaDia);
267
- gruposPorAssinatura.set(assinatura, {
268
- assinatura,
269
- siglaReferencia: siglaDia,
270
- temColunaTurno: infoLinhas.temColunaTurno,
271
- linhasMetadados: infoLinhas.linhas,
272
- dias: []
273
- });
274
- }
275
-
276
- gruposPorAssinatura.get(assinatura).dias.push({
277
- data_slot: dia.data_slot,
278
- tituloDia,
279
- dataCurta,
280
- celulas: mesclarSlotsReservados(slotsReservaveis, 'rowspan')
281
- });
277
+ gruposPorAssinatura.get(assinatura).dias.push({
278
+ data_slot: dia.data_slot,
279
+ tituloDia,
280
+ dataCurta,
281
+ celulas: mesclarSlotsReservados(slotsReservaveis, 'rowspan')
282
282
  });
283
+ });
283
284
 
284
- const listaGrupos = Array.from(gruposPorAssinatura.values());
285
- const maxLinhas = listaGrupos.reduce((acc, g) => Math.max(acc, g.linhasMetadados.length), 0);
286
- const temColunaTurnoPrincipal = listaGrupos[0]?.temColunaTurno || false;
285
+ const listaGrupos = Array.from(gruposPorAssinatura.values());
286
+ const maxLinhas = listaGrupos.reduce((acc, g) => Math.max(acc, g.linhasMetadados.length), 0);
287
+ const temColunaTurnoPrincipal = listaGrupos[0]?.temColunaTurno || false;
287
288
 
288
- return {
289
- grupos: listaGrupos,
290
- maxLinhas,
291
- temColunaTurnoPrincipal
292
- };
289
+ return {
290
+ grupos: listaGrupos,
291
+ maxLinhas,
292
+ temColunaTurnoPrincipal
293
+ };
293
294
  });
294
295
  </script>
295
296
 
296
297
  <template>
297
298
  <div class="tabela-horario-container">
298
- <ModalReserva
299
- v-model="modalAberto"
300
- :dados-iniciais="dadosParaModal"
301
- :usa-interceptador="props.usaInterceptador"
302
- :ocultar-titulo-modal="props.ocultarTituloModal"
303
- @before-save="$emit('before-save', $event)"
304
- @salvo="dispararBuscaSemanal"
305
- >
299
+ <ModalReserva v-model="modalAberto" :dados-iniciais="dadosParaModal" :usa-interceptador="props.usaInterceptador"
300
+ :ocultar-titulo-modal="props.ocultarTituloModal" @before-save="$emit('before-save', $event)"
301
+ @salvo="dispararBuscaSemanal">
306
302
  <template v-for="(_, nomeSlot) in $slots" :key="nomeSlot" #[nomeSlot]="slotProps">
307
303
  <slot :name="nomeSlot" v-bind="slotProps ?? {}"></slot>
308
304
  </template>
309
305
  </ModalReserva>
310
306
 
311
- <ModalDetalhesReserva
312
- v-model="modalDetalhesAberto"
313
- :reserva="reservaSelecionadaDetalhes"
314
- :titulo-padrao="props.tituloPadrao"
315
- @excluido="dispararBuscaSemanal"
316
- />
307
+ <ModalDetalhesReserva v-model="modalDetalhesAberto" :reserva="reservaSelecionadaDetalhes"
308
+ :titulo-padrao="props.tituloPadrao" @excluido="dispararBuscaSemanal" />
317
309
 
318
310
  <div class="aviso-vazio" v-if="carregando">
319
311
  <div class="spinner"></div>
@@ -328,30 +320,24 @@ const estruturaGradeHorario = computed(() => {
328
320
  {{ rec.nome_recurso }}
329
321
  </option>
330
322
  </select>
331
- <span class="dica-arrasto">Dica: Clique em um horário ou segure e arraste para baixo para agendar vários blocos.</span>
323
+ <span class="dica-arrasto">Dica: Clique em um horário ou segure e arraste para baixo para agendar vários
324
+ blocos.</span>
332
325
  </div>
333
326
 
334
327
  <div class="grade-scroll-wrapper">
335
328
  <table class="tabela-estilo-puc">
336
329
  <thead>
337
330
  <tr>
338
- <th
339
- v-if="estruturaGradeHorario.temColunaTurnoPrincipal"
340
- class="th-canto-vazio"
341
- ></th>
331
+ <th v-if="estruturaGradeHorario.temColunaTurnoPrincipal" class="th-canto-vazio"></th>
342
332
 
343
333
  <template v-for="(grupo, idxGrupo) in estruturaGradeHorario.grupos" :key="grupo.assinatura">
344
334
  <th
345
- :class="idxGrupo === 0 ? 'th-cabecalho-padrao th-col-horas' : 'th-cabecalho-especifico th-col-horas'"
346
- >
335
+ :class="idxGrupo === 0 ? 'th-cabecalho-padrao th-col-horas' : 'th-cabecalho-especifico th-col-horas'">
347
336
  HORAS
348
337
  </th>
349
338
 
350
- <th
351
- v-for="dia in grupo.dias"
352
- :key="dia.data_slot"
353
- :class="idxGrupo === 0 ? 'th-cabecalho-padrao' : 'th-cabecalho-especifico'"
354
- >
339
+ <th v-for="dia in grupo.dias" :key="dia.data_slot"
340
+ :class="idxGrupo === 0 ? 'th-cabecalho-padrao' : 'th-cabecalho-especifico'">
355
341
  <div class="th-dia-nome">{{ dia.tituloDia }}</div>
356
342
  <div class="th-dia-data">{{ dia.dataCurta }}</div>
357
343
  </th>
@@ -362,15 +348,11 @@ const estruturaGradeHorario = computed(() => {
362
348
  <tbody>
363
349
  <tr v-for="idxLinha in estruturaGradeHorario.maxLinhas" :key="idxLinha">
364
350
  <template v-if="estruturaGradeHorario.temColunaTurnoPrincipal">
365
- <td
366
- v-if="estruturaGradeHorario.grupos[0]?.linhasMetadados[idxLinha - 1]?.mostrarBlocoLateral"
367
- :rowspan="estruturaGradeHorario.grupos[0].linhasMetadados[idxLinha - 1].rowspanBlocoLateral"
368
- :style="{
351
+ <td v-if="estruturaGradeHorario.grupos[0]?.linhasMetadados[idxLinha - 1]?.mostrarBlocoLateral"
352
+ :rowspan="estruturaGradeHorario.grupos[0].linhasMetadados[idxLinha - 1].rowspanBlocoLateral" :style="{
369
353
  backgroundColor: estruturaGradeHorario.grupos[0].linhasMetadados[idxLinha - 1].corFundo,
370
354
  borderColor: estruturaGradeHorario.grupos[0].linhasMetadados[idxLinha - 1].corBorda
371
- }"
372
- class="td-turno-vertical"
373
- >
355
+ }" class="td-turno-vertical">
374
356
  <div class="texto-turno-vertical">
375
357
  {{ estruturaGradeHorario.grupos[0].linhasMetadados[idxLinha - 1].nomeBlocoLateral }}
376
358
  </div>
@@ -379,17 +361,13 @@ const estruturaGradeHorario = computed(() => {
379
361
 
380
362
  <template v-for="grupo in estruturaGradeHorario.grupos" :key="grupo.assinatura + '-' + idxLinha">
381
363
  <template v-if="(idxLinha - 1) < grupo.linhasMetadados.length">
382
- <td
383
- class="td-celula-horas"
384
- :class="{
385
- 'borda-subbloco': grupo.linhasMetadados[idxLinha - 1]?.fimDeSubbloco,
386
- 'borda-bloco-principal': grupo.linhasMetadados[idxLinha - 1]?.fimDeBlocoPrincipal
387
- }"
388
- :style="{
364
+ <td class="td-celula-horas" :class="{
365
+ 'borda-subbloco': grupo.linhasMetadados[idxLinha - 1]?.fimDeSubbloco,
366
+ 'borda-bloco-principal': grupo.linhasMetadados[idxLinha - 1]?.fimDeBlocoPrincipal
367
+ }" :style="{
389
368
  backgroundColor: grupo.linhasMetadados[idxLinha - 1]?.corFundo,
390
369
  borderColor: grupo.linhasMetadados[idxLinha - 1]?.corBorda
391
- }"
392
- >
370
+ }">
393
371
  <div class="horas-empilhadas">
394
372
  <span>{{ grupo.linhasMetadados[idxLinha - 1]?.horaInicio }}</span>
395
373
  <span>{{ grupo.linhasMetadados[idxLinha - 1]?.horaFim }}</span>
@@ -397,33 +375,26 @@ const estruturaGradeHorario = computed(() => {
397
375
  </td>
398
376
 
399
377
  <template v-for="dia in grupo.dias" :key="dia.data_slot + '-' + idxLinha">
400
- <BlocoArrastavel
401
- v-if="!dia.celulas[idxLinha - 1]?.ocultaPorRowspan"
402
- tag="td"
403
- :grupo="dia.data_slot"
404
- :indice="idxLinha - 1"
405
- :item="dia.celulas[idxLinha - 1]"
378
+ <BlocoArrastavel v-if="!dia.celulas[idxLinha - 1]?.ocultaPorRowspan" tag="td" :grupo="dia.data_slot"
379
+ :indice="idxLinha - 1" :item="dia.celulas[idxLinha - 1]"
406
380
  :disponivel="Boolean(dia.celulas[idxLinha - 1]?.reservavel_slot && !dia.celulas[idxLinha - 1]?.reservado_slot)"
407
- :controlador="controladorArrastoVertical"
408
- :rowspan="dia.celulas[idxLinha - 1]?.rowspan || 1"
409
- class="td-slot-agendavel"
410
- :class="{
381
+ :controlador="controladorArrastoVertical" :rowspan="dia.celulas[idxLinha - 1]?.rowspan || 1"
382
+ class="td-slot-agendavel" :class="{
411
383
  'slot-ocupado': dia.celulas[idxLinha - 1]?.reservado_slot,
412
384
  'slot-api': dia.celulas[idxLinha - 1]?.detalhes_reserva?.origem_criacao_reserva === 'API',
413
385
  'slot-selecionado-arrasto': controladorArrastoVertical.verificarSelecionado(dia.data_slot, idxLinha - 1),
414
386
  'borda-subbloco': grupo.linhasMetadados[(idxLinha - 1) + (dia.celulas[idxLinha - 1]?.rowspan || 1) - 1]?.fimDeSubbloco,
415
387
  'borda-bloco-principal': grupo.linhasMetadados[(idxLinha - 1) + (dia.celulas[idxLinha - 1]?.rowspan || 1) - 1]?.fimDeBlocoPrincipal
416
- }"
417
- :style="{
388
+ }" :style="{
418
389
  backgroundColor: controladorArrastoVertical.verificarSelecionado(dia.data_slot, idxLinha - 1)
419
390
  ? 'var(--color-brand-light)'
420
391
  : grupo.linhasMetadados[idxLinha - 1]?.corFundo,
421
392
  borderColor: grupo.linhasMetadados[idxLinha - 1]?.corBorda
422
- }"
423
- >
393
+ }">
424
394
  <div class="conteudo-slot-horario" v-if="dia.celulas[idxLinha - 1]?.reservado_slot">
425
395
  <span class="titulo-reserva-grade">
426
- {{ dia.celulas[idxLinha - 1]?.detalhes_reserva?.titulo_reserva?.trim() || props.tituloPadrao || 'Reservado' }}
396
+ {{ dia.celulas[idxLinha - 1]?.detalhes_reserva?.titulo_reserva?.trim() || props.tituloPadrao
397
+ || 'Reservado' }}
427
398
  </span>
428
399
  </div>
429
400
  </BlocoArrastavel>
@@ -431,11 +402,9 @@ const estruturaGradeHorario = computed(() => {
431
402
  </template>
432
403
 
433
404
  <template v-else-if="idxLinha - 1 === grupo.linhasMetadados.length">
434
- <td
435
- :colspan="grupo.dias.length + 1"
405
+ <td :colspan="grupo.dias.length + 1"
436
406
  :rowspan="estruturaGradeHorario.maxLinhas - grupo.linhasMetadados.length"
437
- class="td-espaco-vazio-relativo"
438
- ></td>
407
+ class="td-espaco-vazio-relativo"></td>
439
408
  </template>
440
409
  </template>
441
410
  </tr>
@@ -451,42 +420,237 @@ const estruturaGradeHorario = computed(() => {
451
420
  </template>
452
421
 
453
422
  <style scoped>
454
- .tabela-horario-container { width: 100%; height: 100%; background: var(--bg-primary); display: flex; flex-direction: column; user-select: none; }
455
- .horario-conteudo { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
456
- .barra-topo-recurso { display: flex; align-items: center; gap: 12px; padding: 10px 20px; background: var(--bg-primary); border-bottom: 1px solid var(--border-light); font-size: 13.5px; font-weight: 600; color: var(--text-primary); flex-shrink: 0; }
457
- .barra-topo-recurso select { padding: 6px 12px; border-radius: 6px; border: 1px solid var(--border-light); background: var(--bg-secondary); color: var(--text-primary); font-weight: 600; cursor: pointer; }
458
- .dica-arrasto { margin-left: auto; font-size: 12px; font-weight: 500; color: var(--text-secondary); }
459
- .grade-scroll-wrapper { flex-grow: 1; overflow: auto; padding: 16px; background: var(--bg-primary); }
460
- .tabela-estilo-puc { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 12.5px; text-align: center; }
461
-
462
- .th-canto-vazio { width: 36px; min-width: 36px; max-width: 36px; background: transparent !important; border: none !important; }
463
- .th-col-horas { width: 78px; min-width: 78px; max-width: 78px; }
464
- .th-cabecalho-padrao { background-color: #0066B3 !important; color: #FFFFFF !important; font-weight: 800; padding: 8px 6px; border: 1px solid #005291; letter-spacing: 0.4px; position: sticky; top: 0; z-index: 4; }
465
- .th-cabecalho-especifico { background-color: #808080 !important; color: #FFFFFF !important; font-weight: 800; padding: 8px 6px; border: 1px solid #666666; letter-spacing: 0.4px; position: sticky; top: 0; z-index: 4; }
466
- .th-dia-nome { font-size: 13px; line-height: 1.2; }
467
- .th-dia-data { font-size: 10.5px; font-weight: 600; opacity: 0.9; }
468
-
469
- .td-turno-vertical { width: 36px; min-width: 36px; max-width: 36px; border: 1.5px solid; padding: 4px 0; vertical-align: middle; text-align: center; color: #111827 !important; }
470
- .texto-turno-vertical { writing-mode: vertical-rl; transform: rotate(180deg); font-weight: 800; font-size: 13.5px; letter-spacing: 1px; text-transform: uppercase; margin: 0 auto; white-space: nowrap; }
471
- .td-celula-horas { border: 1px solid; padding: 4px 2px; height: 40px; color: #111827 !important; font-weight: 700; font-size: 11.5px; }
472
- .horas-empilhadas { display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.15; }
473
- .td-slot-agendavel { border: 1px solid; padding: 4px 6px; height: 40px; cursor: pointer; transition: filter 0.12s ease, box-shadow 0.12s ease; vertical-align: middle; color: #111827 !important; }
474
- .td-slot-agendavel:hover { filter: brightness(0.93); box-shadow: inset 0 0 0 1.5px var(--color-brand); }
475
- .slot-selecionado-arrasto { box-shadow: inset 0 0 0 2px var(--color-brand) !important; }
423
+ .tabela-horario-container {
424
+ width: 100%;
425
+ height: 100%;
426
+ background: var(--bg-primary);
427
+ display: flex;
428
+ flex-direction: column;
429
+ user-select: none;
430
+ }
431
+
432
+ .horario-conteudo {
433
+ display: flex;
434
+ flex-direction: column;
435
+ height: 100%;
436
+ overflow: hidden;
437
+ }
438
+
439
+ .barra-topo-recurso {
440
+ display: flex;
441
+ align-items: center;
442
+ gap: 12px;
443
+ padding: 10px 20px;
444
+ background: var(--bg-primary);
445
+ border-bottom: 1px solid var(--border-light);
446
+ font-size: 13.5px;
447
+ font-weight: 600;
448
+ color: var(--text-primary);
449
+ flex-shrink: 0;
450
+ }
451
+
452
+ .barra-topo-recurso select {
453
+ padding: 6px 12px;
454
+ border-radius: 6px;
455
+ border: 1px solid var(--border-light);
456
+ background: var(--bg-secondary);
457
+ color: var(--text-primary);
458
+ font-weight: 600;
459
+ cursor: pointer;
460
+ }
461
+
462
+ .dica-arrasto {
463
+ margin-left: auto;
464
+ font-size: 12px;
465
+ font-weight: 500;
466
+ color: var(--text-secondary);
467
+ }
468
+
469
+ .grade-scroll-wrapper {
470
+ flex-grow: 1;
471
+ overflow: auto;
472
+ padding: 16px;
473
+ background: var(--bg-primary);
474
+ }
475
+
476
+ .tabela-estilo-puc {
477
+ width: 100%;
478
+ border-collapse: collapse;
479
+ table-layout: fixed;
480
+ font-size: 12.5px;
481
+ text-align: center;
482
+ }
483
+
484
+ .th-canto-vazio {
485
+ width: 36px;
486
+ min-width: 36px;
487
+ max-width: 36px;
488
+ background: transparent !important;
489
+ border: none !important;
490
+ }
491
+
492
+ .th-col-horas {
493
+ width: 78px;
494
+ min-width: 78px;
495
+ max-width: 78px;
496
+ }
497
+
498
+ .th-cabecalho-padrao {
499
+ background-color: var(--color-brand) !important;
500
+ color: #FFFFFF !important;
501
+ font-weight: 800;
502
+ padding: 8px 6px;
503
+ border: 1px solid #005291;
504
+ letter-spacing: 0.4px;
505
+ position: sticky;
506
+ top: 0;
507
+ z-index: 4;
508
+ border-color: color-mix(in srgb, var(--color-brand) 70%, white) !important;
509
+ }
510
+
511
+ .th-cabecalho-especifico {
512
+ background-color: #808080 !important;
513
+ color: #FFFFFF !important;
514
+ font-weight: 800;
515
+ padding: 8px 6px;
516
+ border: 1px solid #666666;
517
+ letter-spacing: 0.4px;
518
+ position: sticky;
519
+ top: 0;
520
+ z-index: 4;
521
+ }
522
+
523
+ .th-dia-nome {
524
+ font-size: 13px;
525
+ line-height: 1.2;
526
+ }
527
+
528
+ .th-dia-data {
529
+ font-size: 10.5px;
530
+ font-weight: 600;
531
+ opacity: 0.9;
532
+ }
533
+
534
+ .td-turno-vertical {
535
+ width: 36px;
536
+ min-width: 36px;
537
+ max-width: 36px;
538
+ border: 1.5px solid;
539
+ padding: 4px 0;
540
+ vertical-align: middle;
541
+ text-align: center;
542
+ color: #111827 !important;
543
+ }
544
+
545
+ .texto-turno-vertical {
546
+ writing-mode: vertical-rl;
547
+ transform: rotate(180deg);
548
+ font-weight: 800;
549
+ font-size: 13.5px;
550
+ letter-spacing: 1px;
551
+ text-transform: uppercase;
552
+ margin: 0 auto;
553
+ white-space: nowrap;
554
+ }
555
+
556
+ .td-celula-horas {
557
+ border: 1px solid;
558
+ padding: 4px 2px;
559
+ height: 40px;
560
+ color: #111827 !important;
561
+ font-weight: 700;
562
+ font-size: 11.5px;
563
+ }
564
+
565
+ .horas-empilhadas {
566
+ display: flex;
567
+ flex-direction: column;
568
+ align-items: center;
569
+ justify-content: center;
570
+ line-height: 1.15;
571
+ }
572
+
573
+ .td-slot-agendavel {
574
+ border: 1px solid;
575
+ padding: 4px 6px;
576
+ height: 40px;
577
+ cursor: pointer;
578
+ transition: filter 0.12s ease, box-shadow 0.12s ease;
579
+ vertical-align: middle;
580
+ color: #111827 !important;
581
+ }
582
+
583
+ .td-slot-agendavel:hover {
584
+ filter: brightness(0.93);
585
+ box-shadow: inset 0 0 0 1.5px var(--color-brand);
586
+ }
587
+
588
+ .slot-selecionado-arrasto {
589
+ box-shadow: inset 0 0 0 2px var(--color-brand) !important;
590
+ }
591
+
476
592
  .slot-ocupado {
477
- font-weight: 700;
478
- background-color: #e5e7eb !important;
479
- background-image: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.06) 10px, transparent 10px, transparent 20px) !important;
480
- }
481
-
482
- .conteudo-slot-horario { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
483
- .titulo-reserva-grade { font-size: 12px; font-weight: 700; color: #111827; line-height: 1.25; word-break: break-word; }
484
- .borda-subbloco { border-bottom-width: 2px !important; }
485
- .borda-bloco-principal { border-bottom-width: 2.5px !important; }
486
- .td-espaco-vazio-relativo { background: transparent !important; border: none !important; pointer-events: none; }
487
- .aviso-vazio { display: flex; flex-direction: column; justify-content: center; align-items: center; flex-grow: 1; color: var(--text-secondary); font-weight: 500; font-size: 1rem; gap: 12px; }
488
- .spinner { width: 32px; height: 32px; border: 3px solid var(--border-light); border-top-color: var(--color-brand); border-radius: 50%; animation: spin 1s linear infinite; }
489
- @keyframes spin { to { transform: rotate(360deg); } }
593
+ font-weight: 700;
594
+ background-color: #e5e7eb !important;
595
+ background-image: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.06) 10px, transparent 10px, transparent 20px) !important;
596
+ }
597
+
598
+ .conteudo-slot-horario {
599
+ display: flex;
600
+ align-items: center;
601
+ justify-content: center;
602
+ width: 100%;
603
+ height: 100%;
604
+ }
605
+
606
+ .titulo-reserva-grade {
607
+ font-size: 12px;
608
+ font-weight: 700;
609
+ color: #111827;
610
+ line-height: 1.25;
611
+ word-break: break-word;
612
+ }
613
+
614
+ .borda-subbloco {
615
+ border-bottom-width: 2px !important;
616
+ }
617
+
618
+ .borda-bloco-principal {
619
+ border-bottom-width: 2.5px !important;
620
+ }
621
+
622
+ .td-espaco-vazio-relativo {
623
+ background: transparent !important;
624
+ border: none !important;
625
+ pointer-events: none;
626
+ }
627
+
628
+ .aviso-vazio {
629
+ display: flex;
630
+ flex-direction: column;
631
+ justify-content: center;
632
+ align-items: center;
633
+ flex-grow: 1;
634
+ color: var(--text-secondary);
635
+ font-weight: 500;
636
+ font-size: 1rem;
637
+ gap: 12px;
638
+ }
639
+
640
+ .spinner {
641
+ width: 32px;
642
+ height: 32px;
643
+ border: 3px solid var(--border-light);
644
+ border-top-color: var(--color-brand);
645
+ border-radius: 50%;
646
+ animation: spin 1s linear infinite;
647
+ }
648
+
649
+ @keyframes spin {
650
+ to {
651
+ transform: rotate(360deg);
652
+ }
653
+ }
490
654
  </style>
491
655
 
492
656
  <style>
@@ -496,11 +660,20 @@ const estruturaGradeHorario = computed(() => {
496
660
  [data-bs-theme="dark"] .horas-empilhadas span,
497
661
  [data-bs-theme="dark"] .td-slot-agendavel,
498
662
  [data-bs-theme="dark"] .titulo-reserva-grade {
499
- color: var(--text-primary) !important;
663
+ color: var(--text-primary) !important;
500
664
  }
501
665
 
502
666
  [data-bs-theme="dark"] .slot-ocupado {
503
- background-color: #374151 !important;
504
- background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.03) 10px, transparent 10px, transparent 20px) !important;
667
+ background-color: #374151 !important;
668
+ background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.03) 10px, transparent 10px, transparent 20px) !important;
669
+ }
670
+
671
+ [data-bs-theme="dark"] .th-cabecalho-padrao {
672
+ background-color: color-mix(in srgb, var(--color-brand) 50%, black) !important;
673
+ border-color: color-mix(in srgb, var(--color-brand) 70%, black) !important;
674
+ }
675
+ [data-bs-theme="dark"] .th-cabecalho-especifico {
676
+ background-color: #4b5563 !important;
677
+ border-color: #838a95 !important;
505
678
  }
506
679
  </style>