ng-firebase-table-kxp 1.0.9 → 1.0.11
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/esm2020/lib/components/table/table.component.mjs +117 -3
- package/fesm2015/ng-firebase-table-kxp.mjs +117 -2
- package/fesm2015/ng-firebase-table-kxp.mjs.map +1 -1
- package/fesm2020/ng-firebase-table-kxp.mjs +116 -2
- package/fesm2020/ng-firebase-table-kxp.mjs.map +1 -1
- package/lib/components/table/table.component.d.ts +3 -0
- package/package.json +1 -1
|
@@ -1159,6 +1159,7 @@ class TableComponent {
|
|
|
1159
1159
|
this.currentPageNumber = 1;
|
|
1160
1160
|
this.currentClientPageIndex = 0;
|
|
1161
1161
|
this.items = [];
|
|
1162
|
+
this.filteredItems = []; // Dados filtrados para modo não paginado (público para acesso externo)
|
|
1162
1163
|
this.isLoading = false;
|
|
1163
1164
|
this.lastDoc = null;
|
|
1164
1165
|
this.firstDoc = null;
|
|
@@ -1375,9 +1376,22 @@ class TableComponent {
|
|
|
1375
1376
|
await this.loadRelations();
|
|
1376
1377
|
await this.loadQueryLengths();
|
|
1377
1378
|
this.totalItems = this.items.length;
|
|
1379
|
+
// Inicializar arrange para tabelas não paginadas
|
|
1380
|
+
this.arrange = {
|
|
1381
|
+
filters: [],
|
|
1382
|
+
sortBy: this.data.sortBy || {
|
|
1383
|
+
field: 'createdAt',
|
|
1384
|
+
order: 'desc',
|
|
1385
|
+
},
|
|
1386
|
+
};
|
|
1387
|
+
this.sortBy = this.data.sortBy || {
|
|
1388
|
+
field: 'createdAt',
|
|
1389
|
+
order: 'desc',
|
|
1390
|
+
};
|
|
1378
1391
|
// Aplicar filtros client-side se existirem
|
|
1379
1392
|
let itemsToDisplay = [...this.items];
|
|
1380
1393
|
itemsToDisplay = this.applyClientSideFilters(itemsToDisplay);
|
|
1394
|
+
this.filteredItems = itemsToDisplay; // Armazenar dados filtrados
|
|
1381
1395
|
this.dataSource = new MatTableDataSource(itemsToDisplay);
|
|
1382
1396
|
this.dataSource.paginator = this.paginator;
|
|
1383
1397
|
this.dataSource.sort = this.sort;
|
|
@@ -1496,6 +1510,8 @@ class TableComponent {
|
|
|
1496
1510
|
// Handler para mudanças de data no filtro
|
|
1497
1511
|
onDateFilterChange() {
|
|
1498
1512
|
if (this.data.pagination === false) {
|
|
1513
|
+
// Atualizar arrange com os filtros ativos
|
|
1514
|
+
this.arrange = this.buildArrangeFromFilters();
|
|
1499
1515
|
// Aplicar filtros (ou remover se campos estiverem vazios)
|
|
1500
1516
|
this.applyFiltersToDataSource();
|
|
1501
1517
|
}
|
|
@@ -1506,6 +1522,8 @@ class TableComponent {
|
|
|
1506
1522
|
return;
|
|
1507
1523
|
let filteredItems = this.applyClientSideFilters([...this.items]);
|
|
1508
1524
|
this.dataSource.data = filteredItems;
|
|
1525
|
+
// Atualizar filteredItems com os dados filtrados (será atualizado novamente no handleDownload com filteredData)
|
|
1526
|
+
this.filteredItems = filteredItems;
|
|
1509
1527
|
this.totalItems = filteredItems.length;
|
|
1510
1528
|
}
|
|
1511
1529
|
// Métodos com paginação
|
|
@@ -1804,6 +1822,73 @@ class TableComponent {
|
|
|
1804
1822
|
});
|
|
1805
1823
|
}
|
|
1806
1824
|
}
|
|
1825
|
+
buildArrangeFromFilters() {
|
|
1826
|
+
const activeFilters = this.filtersForm.controls
|
|
1827
|
+
.flatMap((control) => {
|
|
1828
|
+
const group = control;
|
|
1829
|
+
const selectedFilter = group.get('selectFilter')?.value;
|
|
1830
|
+
if (!selectedFilter)
|
|
1831
|
+
return [];
|
|
1832
|
+
const arrange = selectedFilter.arrange;
|
|
1833
|
+
if (arrange === 'filter') {
|
|
1834
|
+
const filterValue = group.get('typeFilter')?.value;
|
|
1835
|
+
if (!filterValue)
|
|
1836
|
+
return [];
|
|
1837
|
+
return {
|
|
1838
|
+
arrange,
|
|
1839
|
+
filter: {
|
|
1840
|
+
property: selectedFilter.property,
|
|
1841
|
+
filtering: filterValue,
|
|
1842
|
+
},
|
|
1843
|
+
dateFilter: undefined,
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
if (arrange === 'filterByDate') {
|
|
1847
|
+
const initial = group.get('initialDate')?.value;
|
|
1848
|
+
const final = group.get('finalDate')?.value;
|
|
1849
|
+
if (initial && final) {
|
|
1850
|
+
try {
|
|
1851
|
+
const [dayI, monthI, yearI] = initial.split('/');
|
|
1852
|
+
const initialDate = new Date(`${monthI}/${dayI}/${yearI}`);
|
|
1853
|
+
const [dayF, monthF, yearF] = final.split('/');
|
|
1854
|
+
const finalDate = new Date(`${monthF}/${dayF}/${yearF}`);
|
|
1855
|
+
finalDate.setHours(23, 59, 59);
|
|
1856
|
+
return {
|
|
1857
|
+
arrange,
|
|
1858
|
+
filter: undefined,
|
|
1859
|
+
dateFilter: {
|
|
1860
|
+
initial: initialDate,
|
|
1861
|
+
final: finalDate,
|
|
1862
|
+
},
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
catch (error) {
|
|
1866
|
+
return [];
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
return [];
|
|
1870
|
+
}
|
|
1871
|
+
if (selectedFilter.hasOwnProperty('items') && arrange === 'equals') {
|
|
1872
|
+
const selectedItems = group.get('selectItem')?.value;
|
|
1873
|
+
if (Array.isArray(selectedItems) && selectedItems.length > 0) {
|
|
1874
|
+
return selectedItems.map((item) => ({
|
|
1875
|
+
arrange,
|
|
1876
|
+
filter: {
|
|
1877
|
+
property: item.property,
|
|
1878
|
+
filtering: item.value,
|
|
1879
|
+
},
|
|
1880
|
+
dateFilter: undefined,
|
|
1881
|
+
}));
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
return [];
|
|
1885
|
+
})
|
|
1886
|
+
.filter((f) => f && (f.filter?.filtering !== undefined || f.dateFilter));
|
|
1887
|
+
return {
|
|
1888
|
+
filters: activeFilters,
|
|
1889
|
+
sortBy: this.sortBy,
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1807
1892
|
// Filtro de data
|
|
1808
1893
|
async search() {
|
|
1809
1894
|
if (this.selectSort.value) {
|
|
@@ -1822,6 +1907,8 @@ class TableComponent {
|
|
|
1822
1907
|
}
|
|
1823
1908
|
// Sem paginação: aplicar filtros client-side
|
|
1824
1909
|
if (this.data.pagination === false) {
|
|
1910
|
+
// Atualizar arrange com os filtros ativos
|
|
1911
|
+
this.arrange = this.buildArrangeFromFilters();
|
|
1825
1912
|
this.applyFiltersToDataSource();
|
|
1826
1913
|
this.currentArrange =
|
|
1827
1914
|
this.filtersForm.length > 0
|
|
@@ -1852,6 +1939,11 @@ class TableComponent {
|
|
|
1852
1939
|
};
|
|
1853
1940
|
// Sem paginação: recarregar itens originais
|
|
1854
1941
|
if (this.data.pagination === false) {
|
|
1942
|
+
// Resetar arrange para valores padrão
|
|
1943
|
+
this.arrange = {
|
|
1944
|
+
filters: [],
|
|
1945
|
+
sortBy: this.sortBy,
|
|
1946
|
+
};
|
|
1855
1947
|
this.dataSource.data = [...this.items];
|
|
1856
1948
|
this.totalItems = this.items.length;
|
|
1857
1949
|
this.currentArrange = '';
|
|
@@ -2014,12 +2106,34 @@ class TableComponent {
|
|
|
2014
2106
|
return true;
|
|
2015
2107
|
}
|
|
2016
2108
|
}
|
|
2109
|
+
// Método para lidar com download (diferente para paginado e não paginado)
|
|
2110
|
+
handleDownload() {
|
|
2111
|
+
if (!this.downloadTable)
|
|
2112
|
+
return;
|
|
2113
|
+
// Se não há paginação, usar dados filtrados do dataSource
|
|
2114
|
+
if (this.data.pagination === false) {
|
|
2115
|
+
// Atualizar filteredItems com os dados filtrados do dataSource
|
|
2116
|
+
// (que já inclui filtro de texto aplicado via filterPredicate)
|
|
2117
|
+
if (this.dataSource && this.dataSource.filteredData) {
|
|
2118
|
+
this.filteredItems = [...this.dataSource.filteredData];
|
|
2119
|
+
}
|
|
2120
|
+
// Construir arrange com os filtros ativos (se houver)
|
|
2121
|
+
const arrange = this.buildArrangeFromFilters();
|
|
2122
|
+
this.downloadTable(arrange, this.data.conditions || []);
|
|
2123
|
+
}
|
|
2124
|
+
else {
|
|
2125
|
+
// Modo paginado: usar arrange existente (comportamento original)
|
|
2126
|
+
if (this.arrange) {
|
|
2127
|
+
this.downloadTable(this.arrange, this.data.conditions || []);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2017
2131
|
}
|
|
2018
2132
|
TableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableComponent, deps: [{ token: i1$1.Router }, { token: TableService }, { token: i1.AngularFirestore }], target: i0.ɵɵFactoryTarget.Component });
|
|
2019
|
-
TableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TableComponent, selector: "lib-table", inputs: { data: "data", downloadTable: "downloadTable" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], ngImport: i0, template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title, Custom Action, and Global Actions -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Sort -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Sort Dropdown -->\r\n <div\r\n class=\"w-full sm:w-auto sm:min-w-[250px]\"\r\n *ngIf=\"sortableDropdownItems.length > 0\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Ordenar por</mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && hasFilterableColumn === true\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n <button\r\n *ngIf=\"data.actionButton\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' float-right flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i *ngIf=\"data.actionButton.icon\" [class]=\"data.actionButton.icon\"></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- FILTERS PANEL (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && dropdownItems.length > 0\"\r\n >\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"flex flex-wrap gap-3\">\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Aplicar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <div\r\n class=\"mx-auto flex flex-col\"\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n >\r\n <!-- Calcular quantos grupos de 6 tabs existem -->\r\n <ng-container\r\n *ngFor=\"\r\n let groupIndex of getTabGroups(data.tabs.tabsData);\r\n let i = index\r\n \"\r\n >\r\n <div class=\"mx-auto flex flex-row\">\r\n <ng-container\r\n *ngFor=\"\r\n let tab of getTabGroup(data.tabs.tabsData, groupIndex);\r\n let j = index\r\n \"\r\n >\r\n <button\r\n class=\"border-2 border-gray-300 bg-gray-200 px-4 py-2 font-medium transition hover:brightness-95\"\r\n [ngClass]=\"\r\n isTabSelected(getRealTabIndex(i, j))\r\n ? 'border-b-0 brightness-110'\r\n : ''\r\n \"\r\n (click)=\"onTableSelected(i, j)\"\r\n >\r\n {{ tab.label }}\r\n <span\r\n *ngIf=\"tab.counter !== undefined\"\r\n class=\"ml-2 text-xs font-bold\"\r\n [ngClass]=\"tab.counterClass\"\r\n >\r\n {{ tab.counter }}\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!isLoading\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) || this.data.filterFn\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !isLoading &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <div\r\n *ngIf=\"showTooltip\"\r\n class=\"fixed z-50 max-w-md break-words rounded-lg bg-gray-800 px-3 py-2 text-sm text-white shadow-lg\"\r\n [style.left.px]=\"tooltipPosition.x\"\r\n [style.top.px]=\"tooltipPosition.y\"\r\n [style.pointer-events]=\"'none'\"\r\n >\r\n {{ tooltipContent }}\r\n </div>\r\n</div>\r\n", styles: ["::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i6.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "component", type: i7.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "directive", type: i9.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i10.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i11.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i12.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "directive", type: i13.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i14.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i15.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i16.NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "showTemplate", "clearIfNotMatch", "validation", "separatorLimit", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions"], outputs: ["maskFilled"], exportAs: ["mask", "ngxMask"] }] });
|
|
2133
|
+
TableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TableComponent, selector: "lib-table", inputs: { data: "data", downloadTable: "downloadTable" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], ngImport: i0, template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title, Custom Action, and Global Actions -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Sort -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Sort Dropdown -->\r\n <div\r\n class=\"w-full sm:w-auto sm:min-w-[250px]\"\r\n *ngIf=\"sortableDropdownItems.length > 0\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Ordenar por</mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && hasFilterableColumn === true\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n <button\r\n *ngIf=\"data.actionButton\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' float-right flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i *ngIf=\"data.actionButton.icon\" [class]=\"data.actionButton.icon\"></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- FILTERS PANEL (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && dropdownItems.length > 0\"\r\n >\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"flex flex-wrap gap-3\">\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Aplicar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"handleDownload()\"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <div\r\n class=\"mx-auto flex flex-col\"\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n >\r\n <!-- Calcular quantos grupos de 6 tabs existem -->\r\n <ng-container\r\n *ngFor=\"\r\n let groupIndex of getTabGroups(data.tabs.tabsData);\r\n let i = index\r\n \"\r\n >\r\n <div class=\"mx-auto flex flex-row\">\r\n <ng-container\r\n *ngFor=\"\r\n let tab of getTabGroup(data.tabs.tabsData, groupIndex);\r\n let j = index\r\n \"\r\n >\r\n <button\r\n class=\"border-2 border-gray-300 bg-gray-200 px-4 py-2 font-medium transition hover:brightness-95\"\r\n [ngClass]=\"\r\n isTabSelected(getRealTabIndex(i, j))\r\n ? 'border-b-0 brightness-110'\r\n : ''\r\n \"\r\n (click)=\"onTableSelected(i, j)\"\r\n >\r\n {{ tab.label }}\r\n <span\r\n *ngIf=\"tab.counter !== undefined\"\r\n class=\"ml-2 text-xs font-bold\"\r\n [ngClass]=\"tab.counterClass\"\r\n >\r\n {{ tab.counter }}\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!isLoading\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) || this.data.filterFn\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !isLoading &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <div\r\n *ngIf=\"showTooltip\"\r\n class=\"fixed z-50 max-w-md break-words rounded-lg bg-gray-800 px-3 py-2 text-sm text-white shadow-lg\"\r\n [style.left.px]=\"tooltipPosition.x\"\r\n [style.top.px]=\"tooltipPosition.y\"\r\n [style.pointer-events]=\"'none'\"\r\n >\r\n {{ tooltipContent }}\r\n </div>\r\n</div>\r\n", styles: ["::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i6.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "component", type: i7.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatLabel, selector: "mat-label" }, { kind: "directive", type: i9.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i10.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i11.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i12.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "directive", type: i13.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i14.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i15.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i16.NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "showTemplate", "clearIfNotMatch", "validation", "separatorLimit", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions"], outputs: ["maskFilled"], exportAs: ["mask", "ngxMask"] }] });
|
|
2020
2134
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableComponent, decorators: [{
|
|
2021
2135
|
type: Component,
|
|
2022
|
-
args: [{ selector: 'lib-table', template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title, Custom Action, and Global Actions -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Sort -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Sort Dropdown -->\r\n <div\r\n class=\"w-full sm:w-auto sm:min-w-[250px]\"\r\n *ngIf=\"sortableDropdownItems.length > 0\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Ordenar por</mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && hasFilterableColumn === true\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n <button\r\n *ngIf=\"data.actionButton\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' float-right flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i *ngIf=\"data.actionButton.icon\" [class]=\"data.actionButton.icon\"></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- FILTERS PANEL (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && dropdownItems.length > 0\"\r\n >\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"flex flex-wrap gap-3\">\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Aplicar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <div\r\n class=\"mx-auto flex flex-col\"\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n >\r\n <!-- Calcular quantos grupos de 6 tabs existem -->\r\n <ng-container\r\n *ngFor=\"\r\n let groupIndex of getTabGroups(data.tabs.tabsData);\r\n let i = index\r\n \"\r\n >\r\n <div class=\"mx-auto flex flex-row\">\r\n <ng-container\r\n *ngFor=\"\r\n let tab of getTabGroup(data.tabs.tabsData, groupIndex);\r\n let j = index\r\n \"\r\n >\r\n <button\r\n class=\"border-2 border-gray-300 bg-gray-200 px-4 py-2 font-medium transition hover:brightness-95\"\r\n [ngClass]=\"\r\n isTabSelected(getRealTabIndex(i, j))\r\n ? 'border-b-0 brightness-110'\r\n : ''\r\n \"\r\n (click)=\"onTableSelected(i, j)\"\r\n >\r\n {{ tab.label }}\r\n <span\r\n *ngIf=\"tab.counter !== undefined\"\r\n class=\"ml-2 text-xs font-bold\"\r\n [ngClass]=\"tab.counterClass\"\r\n >\r\n {{ tab.counter }}\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!isLoading\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) || this.data.filterFn\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !isLoading &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <div\r\n *ngIf=\"showTooltip\"\r\n class=\"fixed z-50 max-w-md break-words rounded-lg bg-gray-800 px-3 py-2 text-sm text-white shadow-lg\"\r\n [style.left.px]=\"tooltipPosition.x\"\r\n [style.top.px]=\"tooltipPosition.y\"\r\n [style.pointer-events]=\"'none'\"\r\n >\r\n {{ tooltipContent }}\r\n </div>\r\n</div>\r\n", styles: ["::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}\n"] }]
|
|
2136
|
+
args: [{ selector: 'lib-table', template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title, Custom Action, and Global Actions -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Sort -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Sort Dropdown -->\r\n <div\r\n class=\"w-full sm:w-auto sm:min-w-[250px]\"\r\n *ngIf=\"sortableDropdownItems.length > 0\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Ordenar por</mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && hasFilterableColumn === true\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n <button\r\n *ngIf=\"data.actionButton\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' float-right flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i *ngIf=\"data.actionButton.icon\" [class]=\"data.actionButton.icon\"></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- FILTERS PANEL (for non-paginated tables) -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"data.pagination === false && dropdownItems.length > 0\"\r\n >\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option *ngFor=\"let item of dropdownItems\" [value]=\"item\">\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search()\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n [dropSpecialCharacters]=\"false\"\r\n mask=\"d0/M0/0000\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex flex-col items-center justify-between gap-4 border-t border-gray-200 pt-4 sm:flex-row\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div class=\"flex flex-wrap gap-3\">\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Aplicar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"handleDownload()\"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <div\r\n class=\"mx-auto flex flex-col\"\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n >\r\n <!-- Calcular quantos grupos de 6 tabs existem -->\r\n <ng-container\r\n *ngFor=\"\r\n let groupIndex of getTabGroups(data.tabs.tabsData);\r\n let i = index\r\n \"\r\n >\r\n <div class=\"mx-auto flex flex-row\">\r\n <ng-container\r\n *ngFor=\"\r\n let tab of getTabGroup(data.tabs.tabsData, groupIndex);\r\n let j = index\r\n \"\r\n >\r\n <button\r\n class=\"border-2 border-gray-300 bg-gray-200 px-4 py-2 font-medium transition hover:brightness-95\"\r\n [ngClass]=\"\r\n isTabSelected(getRealTabIndex(i, j))\r\n ? 'border-b-0 brightness-110'\r\n : ''\r\n \"\r\n (click)=\"onTableSelected(i, j)\"\r\n >\r\n {{ tab.label }}\r\n <span\r\n *ngIf=\"tab.counter !== undefined\"\r\n class=\"ml-2 text-xs font-bold\"\r\n [ngClass]=\"tab.counterClass\"\r\n >\r\n {{ tab.counter }}\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n <div class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl\">\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n [ngClass]=\"\r\n (data.color?.bg ? ' ' + $any(data.color).bg : '') +\r\n (data.color?.text ? ' ' + $any(data.color).text : '')\r\n \"\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <img\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n alt=\"Imagem\"\r\n />\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!isLoading\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) || this.data.filterFn\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !isLoading &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <div\r\n *ngIf=\"showTooltip\"\r\n class=\"fixed z-50 max-w-md break-words rounded-lg bg-gray-800 px-3 py-2 text-sm text-white shadow-lg\"\r\n [style.left.px]=\"tooltipPosition.x\"\r\n [style.top.px]=\"tooltipPosition.y\"\r\n [style.pointer-events]=\"'none'\"\r\n >\r\n {{ tooltipContent }}\r\n </div>\r\n</div>\r\n", styles: ["::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}\n"] }]
|
|
2023
2137
|
}], ctorParameters: function () { return [{ type: i1$1.Router }, { type: TableService }, { type: i1.AngularFirestore }]; }, propDecorators: { data: [{
|
|
2024
2138
|
type: Input
|
|
2025
2139
|
}], downloadTable: [{
|