@nixweb/nixloc-ui 1.5.0 → 1.7.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nixweb/nixloc-ui",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Componentes UI",
5
5
  "author": "Fábio Ávila <fabio@nixweb.com.br>",
6
6
  "private": false,
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <div>
4
- <div class="div-btn side-by-side">
4
+ <div v-if="!showSearch" class="div-btn side-by-side">
5
5
  <Button _key="btnShow" color="black" backGroundColor="#F0F0F0"
6
6
  :title="' ' + quantitySelected + ' ' + title + ' selecionado(s)'"
7
7
  classIcon="fa-sharp fa-solid fa-ballot-check" size="small" :clicked="showHide" />
@@ -18,13 +18,18 @@
18
18
  <Loading type="line" :center="false" v-show="loading" />
19
19
  </div>
20
20
  <ScrollBar :minHeight="0" :maxHeight="200">
21
- <div class="div-check">
21
+ <div v-if="multipleSelection" class="div-check">
22
22
  <div class="div-items" v-for="item in data" :key="item.id">
23
23
  <b-form-checkbox v-model="item.selected" @change="add(item)">
24
24
  <span class="title">{{ item.content }}</span>
25
25
  </b-form-checkbox>
26
26
  </div>
27
27
  </div>
28
+ <div v-else class="div-check">
29
+ <b-form-group>
30
+ <b-form-radio-group v-model="selected" :options="options" :stacked="true"></b-form-radio-group>
31
+ </b-form-group>
32
+ </div>
28
33
  <div v-if="totalRecords > 20 && data.length < totalRecords">
29
34
  <div class="after-list text-center">
30
35
  <Button key="loadingMore" type="info" title="Carregar mais..." classIcon="fas fa-redo-alt" size="small"
@@ -52,8 +57,17 @@ export default {
52
57
  props: {
53
58
  title: String,
54
59
  url: String,
60
+ multipleSelection: {
61
+ type: Boolean,
62
+ default: true
63
+ },
64
+ showSearch: {
65
+ type: Boolean,
66
+ default: false
67
+ },
55
68
  propsParams: Object,
56
69
  value: Array,
70
+ changed: Function,
57
71
  },
58
72
  data() {
59
73
  return {
@@ -71,16 +85,23 @@ export default {
71
85
  },
72
86
  mounted() {
73
87
  this.getAll();
74
-
88
+ if (this.showSearch) this.showHide();
75
89
  if (this.value.length > 0) {
76
90
  this.selected = this.value;
77
91
  }
78
-
79
92
  },
80
93
  computed: {
81
94
  ...mapGetters("generic", ["showModal", "event"]),
82
95
  quantitySelected() {
83
96
  return this.selected.length > 0 ? this.selected.length : 0;
97
+ },
98
+ options() {
99
+ let final = [];
100
+ this.data.forEach(item => {
101
+ let obj = { text: item.content, value: item.id };
102
+ final.push(obj);
103
+ });
104
+ return final;
84
105
  }
85
106
  },
86
107
  methods: {
@@ -135,6 +156,7 @@ export default {
135
156
  selected: {
136
157
  handler(value) {
137
158
  this.$emit("input", value);
159
+ if (this.changed) this.changed(value);
138
160
  },
139
161
  deep: true,
140
162
  },
@@ -1,452 +1,193 @@
1
1
  <template>
2
- <div class="date-year-month-wrap">
3
- <div v-if="hasSelection" class="date-year-month-row">
4
- <div class="date-year-month-chip">
5
- <i class="fa-regular fa-calendar"></i>
6
- <span>{{ badgeLabel }}</span>
7
- <button class="date-year-month-chip-close" @click="clearSelection" :disabled="disabled">
8
- <i class="fa-solid fa-xmark"></i>
9
- </button>
10
- </div>
11
- </div>
12
-
13
- <div v-else class="date-year-month-row" ref="anchor">
14
- <div class="date-year-month-group">
15
- <button class="date-year-month-nav date-year-month-year" @click="decYear" :disabled="disabled">
16
- <i class="fa-solid fa-angle-left"></i>
17
- </button>
18
- <span class="date-year-month-label" :class="{ 'date-year-month-muted': disabled }">{{ year }}</span>
19
- <button class="date-year-month-nav date-year-month-year" @click="incYear" :disabled="disabled">
20
- <i class="fa-solid fa-angle-right"></i>
21
- </button>
22
- </div>
23
-
24
- <div class="date-year-month-sep" v-if="mode === 'month'"></div>
25
-
26
- <div class="date-year-month-group" v-if="mode === 'month'">
27
- <button class="date-year-month-nav date-year-month-month" @click="decMonth" :disabled="disabled">
28
- <i class="fa-solid fa-angle-left"></i>
29
- </button>
30
- <span class="date-year-month-label" :class="{ 'date-year-month-muted': disabled }">{{ monthName }}</span>
31
- <button class="date-year-month-nav date-year-month-month" @click="incMonth" :disabled="disabled">
32
- <i class="fa-solid fa-angle-right"></i>
33
- </button>
34
- </div>
35
-
36
- <div class="date-year-month-actions">
37
- <div class="date-year-month-dropdown" ref="dd">
38
- <button class="date-year-month-btn" @click="toggleMenu" :disabled="disabled">
39
- <i class="fa-solid fa-filters"></i>
40
- <span>{{ currentOptionLabel }}</span>
41
- <i class="fa-solid fa-chevron-down"></i>
42
- </button>
43
- <ul v-if="menuOpen" class="date-year-month-menu">
44
- <li class="date-year-month-option" @click="selectOption('today')">Hoje</li>
45
- <li class="date-year-month-option" @click="selectOption('year')">Ano</li>
46
- <li class="date-year-month-option" @click="selectOption('all')">Todos</li>
47
- <li class="date-year-month-option" @click="selectOption('periodCustom')">Vencimento</li>
48
- </ul>
49
- </div>
50
- </div>
51
- </div>
52
-
53
- <transition name="date-year-month-pop">
54
- <div v-if="showRange && !disabled" class="date-year-month-popover" :style="popoverStyle">
55
- <div class="date-year-month-title">Período</div>
56
- <DateTime :confirm="true" :range="true" field="dueDate" format="DD/MM/YYYY" type="date" placeholder
57
- :required="false" v-model="startEnd" />
58
- <div class="date-year-month-actions-row">
59
- <button class="date-year-month-btn date-year-month-btn-ghost" @click="closeRange">Cancelar</button>
60
- <button class="date-year-month-btn date-year-month-btn-apply" :disabled="!startEnd.length"
61
- @click="applyStaticRange">Aplicar</button>
62
- </div>
63
- </div>
64
- </transition>
65
-
66
- <transition name="date-year-month-pop">
67
- <div v-if="showYearPicker && !disabled" class="date-year-month-popover" :style="popoverStyle">
68
- <div class="date-year-month-title">Ano</div>
69
- <div class="date-year-month-year-div">
70
- <div class="date-year-month-year-row">
71
- <button class="date-year-month-year-ctrl" @click="tempYear--" :disabled="tempYear <= 0"><i
72
- class="fa-solid fa-minus"></i></button>
73
- <input class="date-year-month-year-input" type="number" v-model.number="tempYear" />
74
- <button class="date-year-month-year-ctrl" @click="tempYear++"><i class="fa-solid fa-plus"></i></button>
75
- </div>
76
- <div class="date-year-month-actions-row">
77
- <button class="date-year-month-btn date-year-month-btn-ghost" @click="closeYearPicker">Cancelar</button>
78
- <button class="date-year-month-btn date-year-month-btn-apply" @click="applyYear">Aplicar</button>
79
- </div>
80
- </div>
81
- </div>
82
- </transition>
2
+ <div class="date-filter">
3
+ <button @click="previous" class="navigation-button" :class="[buttonClass, { 'disabled': disabled }]"
4
+ :disabled="disabled">
5
+ <i class="fa-solid fa-chevron-left"></i>
6
+ </button>
7
+ <span class="date-display" :class="{ 'title-disabled': disabled }">{{ displayValue }} </span>
8
+ <span class="date-icon" @click="resetSelection()" :class="{ 'disabled': disabled }">
9
+ <i class="fa-solid fa-calendar-week"></i>
10
+ </span>
11
+ <button @click="next" class="navigation-button" :class="[buttonClass, { 'disabled': disabled }]"
12
+ :disabled="disabled">
13
+ <i class="fa-solid fa-chevron-right"></i>
14
+ </button>
83
15
  </div>
84
16
  </template>
85
17
 
86
18
  <script>
87
-
88
- import DateTime from "@nixweb/nixloc-ui/src/component/forms/DateTime";
89
-
90
- const PT_BR_MONTHS = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
19
+ import { mapMutations } from "vuex";
91
20
 
92
21
  export default {
93
- name: "DateYearMonth",
94
- components: {
95
- DateTime
96
- },
97
- model: { prop: "value", event: "input" },
98
22
  props: {
99
- mode: { type: String, required: true, validator: v => ["year", "month"].includes(v) },
23
+ mode: {
24
+ type: String,
25
+ required: true,
26
+ validator(value) {
27
+ return ['month', 'year'].includes(value);
28
+ }
29
+ },
100
30
  value: {
101
- type: Object,
102
- default: () => ({
103
- optionSelected: "",
104
- startEnd: [],
105
- year: new Date().getFullYear(),
106
- month: new Date().getMonth() + 1
107
- })
31
+ type: Number,
32
+ required: false
108
33
  },
109
- disabled: { type: Boolean, default: false }
34
+ disabled: {
35
+ type: Boolean,
36
+ default: false
37
+ }
110
38
  },
111
39
  data() {
112
- const v = this.value || {};
113
40
  return {
114
- optionSelected: v.optionSelected || "",
115
- startEnd: Array.isArray(v.startEnd) ? v.startEnd : [],
116
- year: Number.isFinite(v.year) ? v.year : new Date().getFullYear(),
117
- month: Number.isFinite(v.month) ? v.month : (new Date().getMonth() + 1),
118
- showRange: false,
119
- showYearPicker: false,
120
- tempYear: Number.isFinite(v.year) ? v.year : new Date().getFullYear(),
121
- popoverStyle: {},
122
- menuOpen: false
41
+ currentMonth: new Date().getMonth(),
42
+ currentYear: new Date().getFullYear()
123
43
  };
124
44
  },
125
- created() { this.emitChanged(); },
126
- computed: {
127
- monthName() { return PT_BR_MONTHS[(this.month - 1 + 12) % 12]; },
128
- hasSelection() { return ["all", "today", "periodCustom", "year"].includes(this.optionSelected); },
129
- badgeLabel() {
130
- if (this.optionSelected === "all") return "Todos";
131
- if (this.optionSelected === "today") return "Hoje";
132
- if (this.optionSelected === "year") return `Ano ${this.year}`;
133
- if (this.optionSelected === "periodCustom") return `${this.startEnd[0]} — ${this.startEnd[1]}`;
134
- return "";
135
- },
136
- currentOptionLabel() {
137
- if (this.optionSelected === "all") return "Todos";
138
- if (this.optionSelected === "today") return "Hoje";
139
- if (this.optionSelected === "year") return "Ano";
140
- if (this.optionSelected === "periodCustom") return "Personalizado";
141
- return "Mais";
142
- }
45
+ created() {
46
+ this.resetSelection();
143
47
  },
144
- watch: {
145
- value: {
146
- deep: true,
147
- handler(v) {
148
- if (!v) return;
149
- this.optionSelected = v.optionSelected || "";
150
- this.startEnd = Array.isArray(v.startEnd) ? v.startEnd : [];
151
- if (Number.isFinite(v.year)) { this.year = v.year; this.tempYear = v.year; }
152
- if (Number.isFinite(v.month)) this.month = v.month;
48
+ mounted() {
49
+ this.sendEvent();
50
+ },
51
+ computed: {
52
+ displayValue() {
53
+ if (this.mode === 'month') {
54
+ return this.monthNames[this.currentMonth];
55
+ } else {
56
+ return this.currentYear;
153
57
  }
58
+ },
59
+ monthNames() {
60
+ return ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'];
61
+ },
62
+ buttonClass() {
63
+ return this.mode === 'month' ? 'month-mode' : 'year-mode';
154
64
  }
155
65
  },
156
66
  methods: {
157
- payload() {
158
- return {
159
- optionSelected: this.optionSelected,
160
- startEnd: this.optionSelected === "periodCustom" ? this.startEnd : [],
161
- year: this.year,
162
- month: this.month
163
- };
164
- },
165
- emitChanged() {
166
- const p = this.payload();
167
- this.$emit("input", p);
168
- this.$emit("changed", p);
169
- },
170
- // navegação padrão
171
- decYear() { if (this.disabled) return; this.year--; this.emitChanged(); },
172
- incYear() { if (this.disabled) return; this.year++; this.emitChanged(); },
173
- decMonth() {
174
- if (this.disabled || this.mode !== "month") return;
175
- if (this.month === 1) { this.month = 12; this.year--; } else { this.month--; }
176
- this.emitChanged();
177
- },
178
- incMonth() {
179
- if (this.disabled || this.mode !== "month") return;
180
- if (this.month === 12) { this.month = 1; this.year++; } else { this.month++; }
181
- this.emitChanged();
182
- },
183
- // dropdown
184
- toggleMenu() {
67
+ ...mapMutations("generic", ["addEvent"]),
68
+ previous() {
185
69
  if (this.disabled) return;
186
- this.menuOpen = !this.menuOpen;
187
- if (this.menuOpen) document.addEventListener("click", this.onClickOutside);
188
- },
189
- onClickOutside(e) {
190
- const root = this.$refs.dd;
191
- if (root && !root.contains(e.target)) {
192
- this.menuOpen = false;
193
- document.removeEventListener("click", this.onClickOutside);
70
+ if (this.mode === 'month') {
71
+ this.currentMonth = (this.currentMonth + 11) % 12;
72
+ if (this.currentMonth === 11) {
73
+ this.currentYear--;
74
+ }
75
+ } else {
76
+ this.currentYear--;
194
77
  }
78
+ this.$emit('input', this.getValue());
79
+ this.sendEvent();
195
80
  },
196
- selectOption(opt) {
197
- this.menuOpen = false;
198
- if (opt === "all") { this.optionSelected = "all"; this.startEnd = []; this.emitChanged(); return; }
199
- if (opt === "today") { this.optionSelected = "today"; this.startEnd = []; this.emitChanged(); return; }
200
- if (opt === "year") { this.openYearPicker(); return; }
201
- this.openCustom();
202
- },
203
- // período custom (estático)
204
- openCustom() { this.positionPopover(); this.showRange = true; },
205
- closeRange() { this.showRange = false; },
206
- applyStaticRange() {
207
- this.optionSelected = "periodCustom";
208
- this.showRange = false;
209
- this.emitChanged();
81
+ next() {
82
+ if (this.disabled) return;
83
+ if (this.mode === 'month') {
84
+ this.currentMonth = (this.currentMonth + 1) % 12;
85
+ if (this.currentMonth === 0) {
86
+ this.currentYear++;
87
+ }
88
+ } else {
89
+ this.currentYear++;
90
+ }
91
+ this.$emit('input', this.getValue());
92
+ this.sendEvent();
210
93
  },
211
- // ano custom
212
- openYearPicker() {
213
- this.positionPopover();
214
- this.tempYear = this.year || new Date().getFullYear();
215
- this.showYearPicker = true;
94
+ resetSelection() {
95
+ const now = new Date();
96
+ if (this.mode === 'month') {
97
+ this.currentMonth = now.getMonth();
98
+ this.currentYear = now.getFullYear();
99
+ } else {
100
+ this.currentYear = now.getFullYear();
101
+ }
102
+ this.sendEvent();
216
103
  },
217
- closeYearPicker() { this.showYearPicker = false; },
218
- applyYear() {
219
- const y = Number(this.tempYear);
220
- if (Number.isFinite(y)) {
221
- this.year = y;
222
- this.optionSelected = "year";
223
- this.emitChanged();
104
+ getValue() {
105
+ if (this.mode === 'month') {
106
+ return (this.currentMonth + 1).toString();
107
+ } else {
108
+ return this.currentYear.toString();
224
109
  }
225
- this.showYearPicker = false;
226
110
  },
227
- // limpar seleção volta pro padrão (mês/ano atual)
228
- clearSelection() {
229
- this.optionSelected = "";
230
- this.startEnd = [];
231
- const now = new Date();
232
- this.year = now.getFullYear();
233
- this.month = now.getMonth() + 1;
234
- this.showRange = false;
235
- this.showYearPicker = false;
236
- this.emitChanged();
111
+ sendEvent() {
112
+ this.addEvent({ name: "dateYearMonth", data: { mode: this.mode, value: this.getValue() } });
113
+ this.$emit('input', this.getValue());
114
+ }
115
+ },
116
+ watch: {
117
+ mode(newMode) {
118
+ this.resetSelection();
237
119
  },
238
- positionPopover() {
239
- this.$nextTick(() => {
240
- const el = this.$refs.anchor; if (!el) return;
241
- const r = el.getBoundingClientRect();
242
- this.popoverStyle = { left: r.left + "px", top: (r.bottom + 8) + "px", minWidth: r.width + "px", position: "fixed" };
243
- });
120
+ value(newValue) {
121
+ if (this.mode === 'month') {
122
+ this.currentMonth = newValue - 1;
123
+ } else {
124
+ this.currentYear = newValue;
125
+ }
244
126
  }
245
- }
127
+ },
246
128
  };
247
129
  </script>
248
130
 
249
131
  <style scoped>
250
- .date-year-month-wrap {
251
- position: relative;
252
- display: inline-block
253
- }
254
-
255
- .date-year-month-row {
132
+ .date-filter {
256
133
  display: flex;
257
134
  align-items: center;
258
- gap: 12px;
259
- flex-wrap: wrap;
260
- justify-content: flex-start
261
- }
262
-
263
- .date-year-month-actions {
264
- margin-left: auto;
265
- position: relative
266
- }
267
-
268
- .date-year-month-btn {
269
- display: inline-flex;
270
- align-items: center;
271
- gap: 8px;
272
- height: 32px;
273
- padding: 0 12px;
274
- border-radius: 999px;
275
- background: #F0F0F0;
276
- border: 1px solid #e5e7eb;
277
- font-size: 13px;
278
- letter-spacing: 1px;
279
- cursor: pointer
280
- }
281
-
282
- .date-year-month-dropdown {
283
- position: relative
284
- }
285
-
286
- .date-year-month-menu {
287
- position: absolute;
288
- top: 38px;
289
- right: 0;
290
- list-style: none;
291
- margin: 0;
292
- padding: 6px;
293
- background: #fff;
294
- border: 1px solid #e5e7eb;
295
- border-radius: 10px;
296
- min-width: 150px;
297
- box-shadow: 0 10px 24px rgba(16, 24, 40, .12);
298
- z-index: 1001
299
- }
300
-
301
- .date-year-month-menu li {
302
- padding: 8px 10px;
303
- border-radius: 8px;
304
- cursor: pointer;
305
- font-weight: 500;
306
- color: #374151
307
- }
308
-
309
- .date-year-month-menu li:hover {
310
- background: #f3f4f6
311
- }
312
-
313
- .date-year-month-group {
314
- display: inline-flex;
315
- align-items: center;
316
- gap: 8px
317
- }
318
-
319
- .date-year-month-label {
320
- font-weight: 700;
321
- color: #1f2937
322
- }
323
-
324
- .date-year-month-muted {
325
- color: #9ca3af
135
+ justify-content: center;
136
+ gap: 20px;
326
137
  }
327
138
 
328
- .date-year-month-sep {
329
- width: 1px;
330
- height: 22px;
331
- background: #e5e7eb;
332
- border-radius: 1px
333
- }
334
-
335
- .date-year-month-nav {
336
- width: 32px;
337
- height: 32px;
338
- border-radius: 999px;
139
+ .navigation-button {
140
+ color: white;
339
141
  border: none;
340
- cursor: pointer;
341
- color: #fff;
342
- display: inline-flex;
343
- align-items: center;
344
- justify-content: center
345
- }
346
-
347
- .date-year-month-year {
348
- background: #3b82f6
349
- }
350
-
351
- .date-year-month-month {
352
- background: #f59e0b
353
- }
354
-
355
- .date-year-month-chip {
356
- display: inline-flex;
142
+ border-radius: 50%;
143
+ width: 30px;
144
+ height: 30px;
145
+ display: flex;
357
146
  align-items: center;
358
- gap: 8px;
359
- padding: 6px 10px;
360
- border-radius: 999px;
361
- background: #f3f4f6;
362
- border: 1px solid #e5e7eb;
363
- font-weight: 600;
364
- color: #111827
365
- }
366
-
367
- .date-year-month-chip-close {
368
- border: none;
369
- background: transparent;
147
+ justify-content: center;
148
+ font-size: 1.2em;
370
149
  cursor: pointer;
371
- color: #6b7280;
372
- display: inline-flex;
373
- align-items: center
150
+ transition: background-color 0.3s, transform 0.2s;
374
151
  }
375
152
 
376
- .date-year-month-pop-enter-active,
377
- .date-year-month-pop-leave-active {
378
- transition: all .18s ease
153
+ .navigation-button:hover {
154
+ opacity: 0.8;
379
155
  }
380
156
 
381
- .date-year-month-pop-enter-from,
382
- .date-year-month-pop-leave-to {
383
- opacity: 0;
384
- transform: translateY(-4px)
157
+ .navigation-button:active {
158
+ transform: scale(0.95);
385
159
  }
386
160
 
387
- .date-year-month-popover {
388
- z-index: 1000;
389
- background: #fff;
390
- border: 1px solid #e5e7eb;
391
- border-radius: 12px;
392
- padding: 12px;
393
- box-shadow: 0 10px 24px rgba(16, 24, 40, .12)
161
+ .navigation-button.disabled {
162
+ background-color: #b0b0b0;
163
+ opacity: 0.5;
164
+ cursor: not-allowed;
394
165
  }
395
166
 
396
- .date-year-month-title {
397
- font-weight: 700;
398
- color: #1f2937;
399
- margin-bottom: 8px
167
+ .date-display {
168
+ font-size: 1.5em;
169
+ font-weight: bold;
400
170
  }
401
171
 
402
- .date-year-month-year-div {
403
- margin: 0px 0px 0px 100px;
172
+ .month-mode {
173
+ background-color: #ffa500;
404
174
  }
405
175
 
406
- .date-year-month-actions-row {
407
- display: flex;
408
- justify-content: flex-end;
409
- gap: 8px;
410
- margin-top: 20px
176
+ .year-mode {
177
+ background-color: #007bff;
411
178
  }
412
179
 
413
- .date-year-month-btn-ghost {
414
- background: transparent;
415
- border: 1px solid #e5e7eb
416
- }
417
-
418
- .date-year-month-btn-apply {
419
- background: #0ea5e9;
420
- border: 1px solid #fff;
421
- color: #fff
422
- }
423
-
424
- .date-year-month-btn-apply:hover {
425
- background: #3E90B3;
426
- }
427
-
428
- .date-year-month-year-row {
429
- display: flex;
430
- align-items: center;
431
- gap: 8px;
432
- margin: 6px 0 2px
180
+ .date-icon {
181
+ cursor: pointer;
182
+ color: rgb(73, 72, 72);
433
183
  }
434
184
 
435
- .date-year-month-year-input {
436
- height: 34px;
437
- width: 110px;
438
- text-align: center;
439
- border: 1px solid #e5e7eb;
440
- border-radius: 8px
185
+ .title-disabled {
186
+ color: #b0b0b0;
441
187
  }
442
188
 
443
- .date-year-month-year-ctrl {
444
- height: 32px;
445
- width: 32px;
446
- border-radius: 50px;
447
- border: 1px solid #3C82F6;
448
- color: white;
449
- background: #3C82F6;
450
- cursor: pointer
189
+ .date-icon.disabled {
190
+ color: #b0b0b0;
191
+ cursor: not-allowed;
451
192
  }
452
- </style>
193
+ </style>
@@ -3,7 +3,6 @@
3
3
  <div ref='preview'>
4
4
  <v-runtime-template :template="`<div>${template}</div>`" />
5
5
  </div>
6
- <div>{{ template }}</div>
7
6
  </div>
8
7
  </template>
9
8
 
@@ -113,7 +113,7 @@ export default {
113
113
 
114
114
  const tabelaGrupoSubGrupo = "t.produtoGrupoSubgrupo";
115
115
  const idxMarker = documentHtml.indexOf(tabelaGrupoSubGrupo);
116
- const marcadorDiv = '<tabela-grupo-subgrupo></tabela-grupo-subgrupo>';
116
+ const marcadorDiv = `<tabela-grupo-subgrupo></tabela-grupo-subgrupo>`;
117
117
 
118
118
  if (idxMarker !== -1) {
119
119
  tableStart = documentHtml.lastIndexOf("<table", idxMarker);
@@ -156,6 +156,7 @@ export default {
156
156
  let isProduct = th.innerText.includes("t.produtoLocacao");
157
157
  let isInvoice = th.innerText.includes("t.produtoFatura");
158
158
  let isGrouped = th.innerText.includes("t.produtoAgrupado");
159
+ let isGroupedSubgroup = th.innerText.includes("t.produtoGrupoSubgrupo");
159
160
  let isMoviment = th.innerText.includes("t.produtoMovimentacao");
160
161
  let isCustumerAddress = th.innerText.includes("t.enderecoCliente");
161
162
  let isAddressRent = th.innerText.includes("t.saidaRetornoLocacao");
@@ -208,7 +209,10 @@ export default {
208
209
 
209
210
  config.push(obj);
210
211
 
211
- } else if (isMoviment) {
212
+ } else if (isGroupedSubgroup) {
213
+ // não faz nda, quem altera essa tabela é a após retParse
214
+ }
215
+ else if (isMoviment) {
212
216
  obj.vForSimple = "v-for='produto in d.itensMovimentacao'";
213
217
  config.push(obj);
214
218
  } else if (isCustumerAddress) {
@@ -231,16 +235,53 @@ export default {
231
235
 
232
236
  let replace = "";
233
237
  config.forEach(x => {
234
- if (x.nameGroup || x.vForGrouped || x.nameGroupReplace || x.vForSimple) {
235
- replace += `.replace("<tbody>${x.nameGroup}<tr>", "<tbody ${x.vForGrouped}>${x.nameGroupReplace}<tr ${x.vForSimple}>")`;
236
- }
238
+ replace += `.replace("<tbody>${x.nameGroup}<tr>", "<tbody ${x.vForGrouped}>${x.nameGroupReplace}<tr ${x.vForSimple}>")`;
237
239
  });
238
240
 
239
241
  var retParse = ret.replaceAll("\"", "'");
240
242
  retParse = eval(`retParse${replace}`);
241
243
 
242
- if (removedTableHtml)
244
+ if (removedTableHtml) {
245
+
246
+ removedTableHtml = removedTableHtml.replace("<tbody>", `<tbody v-for="(grupos, grupoMaster) in produtoGrupoSubgrupo">`);
247
+
248
+ const inicio = removedTableHtml.indexOf("<tbody");
249
+ const fim = removedTableHtml.indexOf("</tbody>", inicio) + "</tbody>".length;
250
+ let tbodyHtml = removedTableHtml.substring(inicio, fim);
251
+ const trs = [...tbodyHtml.matchAll(/<tr[^>]*>/g)];
252
+ if (trs.length >= 3) {
253
+ const grupoStart = trs[1].index;
254
+ const produtoStart = trs[2].index;
255
+ const produtoEnd = tbodyHtml.indexOf("</tr>", produtoStart) + "</tr>".length;
256
+
257
+ const wrapStart = grupoStart;
258
+ const wrapEnd = produtoEnd;
259
+
260
+ let templateContent = tbodyHtml.substring(wrapStart, wrapEnd);
261
+
262
+ const innerTrs = [...templateContent.matchAll(/<tr[^>]*>/g)];
263
+ if (innerTrs.length >= 2) {
264
+ const prodTag = innerTrs[1];
265
+ const pStart = prodTag.index;
266
+ const pEnd = pStart + prodTag[0].length;
267
+
268
+ templateContent =
269
+ templateContent.substring(0, pStart) +
270
+ `<tr v-for="produto in itensLocacao">` +
271
+ templateContent.substring(pEnd);
272
+ }
273
+
274
+ tbodyHtml = tbodyHtml.substring(0, wrapStart) +
275
+ `<template v-for="(itensLocacao, grupo) in grupos">` +
276
+ templateContent +
277
+ `</template>` +
278
+ tbodyHtml.substring(wrapEnd);
279
+
280
+ removedTableHtml = removedTableHtml.substring(0, inicio) + tbodyHtml + removedTableHtml.substring(fim);
281
+ }
282
+
243
283
  retParse = retParse.replace(marcadorDiv, `<div>${removedTableHtml}</div>`);
284
+ }
244
285
 
245
286
  var classImportant = retParse
246
287
  .replaceAll("t.pagamentoLocacao", "")