feat: várias melhorias e evoluções no projeto
This commit is contained in:
242
frontend/js/script.js
Normal file
242
frontend/js/script.js
Normal file
@ -0,0 +1,242 @@
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('searchApp', () => ({
|
||||
searchParams: {
|
||||
q: '',
|
||||
numero_diario: '',
|
||||
data_inicio: '',
|
||||
data_fim: '',
|
||||
modo_busca: 'exata',
|
||||
ordenar_por: 'data_asc',
|
||||
page: 1,
|
||||
page_size: 10
|
||||
},
|
||||
searchResults: null,
|
||||
isLoading: false,
|
||||
hasSearched: false,
|
||||
error: null,
|
||||
showAdvanced: false,
|
||||
expandedContents: {},
|
||||
suggestion: null,
|
||||
ultimoTermoBuscado: '',
|
||||
|
||||
get shouldShowSuggestion() {
|
||||
if (!this.suggestion || !this.searchParams.q) return false;
|
||||
|
||||
// Função para remover acentos e converter para minúsculas
|
||||
const normalize = (text) => {
|
||||
return text.toLowerCase()
|
||||
.normalize('NFD')
|
||||
.replace("/", " ")
|
||||
.replace(/[^a-z0-9\s]/g, " ") // Substitui todos os outros símbolos por espaço
|
||||
.replace(/[\u0300-\u036f]/g, '');
|
||||
};
|
||||
|
||||
const normalizedQuery = normalize(this.searchParams.q);
|
||||
const normalizedSuggestion = normalize(this.suggestion);
|
||||
|
||||
// Só mostra a sugestão se for diferente do termo buscado (ignorando acentos e caixa)
|
||||
return normalizedQuery !== normalizedSuggestion;
|
||||
},
|
||||
|
||||
// Usa a sugestão como novo termo de busca
|
||||
usesuggestion() {
|
||||
this.searchParams.q = this.suggestion;
|
||||
this.searchParams.page = 1;
|
||||
this.performSearch();
|
||||
},
|
||||
|
||||
// Verifica se um diário tem uma melhor correspondência
|
||||
hasBestMatch(diario) {
|
||||
return diario.paginas && diario.paginas.length > 0;
|
||||
},
|
||||
|
||||
// Muda a ordenação e faz uma nova busca
|
||||
changeOrder(order) {
|
||||
if (this.searchParams.ordenar_por !== order) {
|
||||
this.searchParams.ordenar_por = order;
|
||||
this.searchParams.page = 1; // Volta para a primeira página
|
||||
this.performSearch();
|
||||
}
|
||||
},
|
||||
|
||||
// Obter sugestão da API
|
||||
async getSuggestion(query) {
|
||||
if (!query) return null;
|
||||
|
||||
try {
|
||||
const url = new URL('http://109.199.98.226:8005/api/v1/diarios/sugestao');
|
||||
url.searchParams.append('q', query);
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data.sugestao;
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('Erro ao buscar sugestão:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
get totalPages() {
|
||||
if (!this.searchResults) return 0;
|
||||
return Math.ceil(this.searchResults.total / this.searchResults.por_pagina);
|
||||
},
|
||||
|
||||
get paginationArray() {
|
||||
const pages = [];
|
||||
const currentPage = this.searchParams.page;
|
||||
const totalPages = this.totalPages;
|
||||
|
||||
// Função auxiliar para adicionar páginas
|
||||
const addPage = (page) => {
|
||||
if (page >= 1 && page <= totalPages && !pages.includes(page)) {
|
||||
pages.push(page);
|
||||
}
|
||||
};
|
||||
|
||||
// Sempre mostrar primeira página, página atual, última página
|
||||
// e 1-2 páginas adjacentes à página atual
|
||||
addPage(1);
|
||||
addPage(currentPage - 2);
|
||||
addPage(currentPage - 1);
|
||||
addPage(currentPage);
|
||||
addPage(currentPage + 1);
|
||||
addPage(currentPage + 2);
|
||||
addPage(totalPages);
|
||||
|
||||
// Ordenar e adicionar separadores
|
||||
const result = pages.sort((a, b) => a - b);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
// Retorna a melhor página (maior score) de um diário
|
||||
getBestPage(paginas) {
|
||||
if (!paginas || paginas.length === 0) return null;
|
||||
|
||||
// Ordena as páginas por score (se disponível) ou pelo número da página se não houver score
|
||||
const sortedPages = [...paginas].sort((a, b) => {
|
||||
if (a.score === undefined || b.score === undefined) return 0;
|
||||
if (a.score === undefined) return 1;
|
||||
if (b.score === undefined) return -1;
|
||||
return b.score - a.score;
|
||||
});
|
||||
|
||||
return sortedPages[0];
|
||||
},
|
||||
|
||||
// Retorna todas as páginas exceto a melhor
|
||||
getOtherPages(paginas) {
|
||||
if (!paginas || paginas.length <= 1) return [];
|
||||
|
||||
const bestPage = this.getBestPage(paginas);
|
||||
if (!bestPage) return paginas;
|
||||
|
||||
return paginas.filter(p => p.numero !== bestPage.numero)
|
||||
.sort((a, b) => a.numero - b.numero); // Ordena por número da página
|
||||
},
|
||||
|
||||
// Controla a exibição do conteúdo completo de uma página
|
||||
toggleFullContent(diarioIndex, paginaNumero) {
|
||||
const key = `${diarioIndex}-${paginaNumero}`;
|
||||
this.expandedContents[key] = !this.expandedContents[key];
|
||||
},
|
||||
|
||||
// Verifica se um conteúdo está expandido
|
||||
isFullContentVisible(diarioIndex, paginaNumero) {
|
||||
const key = `${diarioIndex}-${paginaNumero}`;
|
||||
return this.expandedContents[key] === true;
|
||||
},
|
||||
|
||||
async performSearch() {
|
||||
this.isLoading = true;
|
||||
this.error = null;
|
||||
this.hasSearched = true;
|
||||
this.expandedContents = {}; // Resetar estados expandidos
|
||||
this.suggestion = null; // Resetar a sugestão
|
||||
|
||||
try {
|
||||
let suggestionPromise = null;
|
||||
if (this.searchParams.q) {
|
||||
suggestionPromise = this.getSuggestion(this.searchParams.q);
|
||||
}
|
||||
if (this.searchParams.q !== this.ultimoTermoBuscado) {
|
||||
this.searchParams.page = 1;
|
||||
}
|
||||
this.ultimoTermoBuscado = this.searchParams.q;
|
||||
// Usando agora o endpoint busca
|
||||
const url = new URL('http://109.199.98.226:8005/api/v1/diarios/busca');
|
||||
|
||||
// Adicionar parâmetros à URL
|
||||
Object.entries(this.searchParams).forEach(([key, value]) => {
|
||||
if (value !== '' && value !== null) {
|
||||
url.searchParams.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null);
|
||||
throw new Error(errorData?.message || `Erro HTTP: ${response.status}`);
|
||||
}
|
||||
|
||||
this.searchResults = await response.json();
|
||||
|
||||
// Processar os resultados para garantir que as páginas tenham score
|
||||
if (this.searchResults && this.searchResults.resultados) {
|
||||
this.searchResults.resultados.forEach(diario => {
|
||||
if (diario.paginas) {
|
||||
// Atribuir scores padrão se não existirem
|
||||
diario.paginas.forEach((pagina, index) => {
|
||||
if (pagina.score === undefined || pagina.score === null) {
|
||||
pagina.score = diario.paginas.length - index; // Score inversamente proporcional ao índice
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (suggestionPromise) {
|
||||
this.suggestion = await suggestionPromise;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro na busca:', error);
|
||||
this.error = `Erro ao buscar diários: ${error.message}`;
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
formatDate(dateString) {
|
||||
const options = { day: '2-digit', month: '2-digit', year: 'numeric' };
|
||||
return new Date(dateString + 'T00:00:00').toLocaleDateString('pt-BR', options);
|
||||
},
|
||||
goToPage(page) {
|
||||
if (page < 1 || page > this.totalPages) return;
|
||||
this.searchParams.page = page;
|
||||
this.performSearch();
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
this.searchParams = {
|
||||
q: '',
|
||||
numero_diario: '',
|
||||
data_inicio: '',
|
||||
data_fim: '',
|
||||
modo_busca: 'exata',
|
||||
ordenar_por: 'relevancia',
|
||||
page: 1,
|
||||
page_size: 10
|
||||
};
|
||||
this.searchResults = null;
|
||||
this.hasSearched = false;
|
||||
this.error = null;
|
||||
this.expandedContents = {};
|
||||
}
|
||||
}));
|
||||
});
|
||||
Reference in New Issue
Block a user