Skip to content

Commit 781e8c1

Browse files
ajuste ordenação projetos
1 parent 8c92f23 commit 781e8c1

File tree

1 file changed

+253
-34
lines changed

1 file changed

+253
-34
lines changed
Lines changed: 253 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,263 @@
11
---
22
const { textos, iniciativas, projetos = [] } = Astro.props;
3+
4+
// Usar os dados do JSON fornecido
5+
const projetosData = iniciativas?.projetosLista || projetos || [];
6+
7+
console.log("Total de projetos:", projetosData.length);
8+
console.log("Estrutura do primeiro projeto:", Object.keys(projetosData[0] || {}));
9+
10+
// Obter parâmetro de ordenação da URL
11+
const url = new URL(Astro.request.url);
12+
const ordemValida = ["titulo", "docente", "periodo"];
13+
const ordemParam = url.searchParams.get("ordem") ?? "";
14+
15+
console.log("Parâmetro 'ordem' da URL:", ordemParam);
16+
17+
// Determinar ordem final
18+
const ordem = ordemValida.includes(ordemParam)? ordemParam : "titulo";
19+
console.log("Ordem selecionada:", ordem);
20+
21+
const getOrdenado = (ordem: string) => {
22+
return [...projetosData].sort((a, b) => {
23+
const valorA = (a[ordem] ?? "").toString().trim().toLowerCase();
24+
const valorB = (b[ordem] ?? "").toString().trim().toLowerCase();
25+
26+
if (ordem === "periodo") {
27+
const anoA = parseInt(valorA.match(/(\d{4})/)?.[1] || "0");
28+
const anoB = parseInt(valorB.match(/(\d{4})/)?.[1] || "0");
29+
return anoA - anoB;
30+
}
31+
32+
return valorA.localeCompare(valorB, 'pt-BR', { sensitivity: 'base' });
33+
});
34+
}
35+
const projetosOrdenados = getOrdenado(ordem);
36+
37+
// Função para escapar HTML
38+
const escapeHtml = (text) => {
39+
if (!text) return '';
40+
return text.toString()
41+
.replace(/&/g, '&')
42+
.replace(/</g, '&lt;')
43+
.replace(/>/g, '&gt;')
44+
.replace(/"/g, '&quot;')
45+
.replace(/'/g, '&#39;');
46+
};
347
---
448

549
<section class="max-w-5xl mx-auto px-4 py-16 space-y-8">
6-
<!-- Título e descrição -->
7-
<h1 class="text-3xl font-bold text-primary">
8-
{iniciativas?.projetosDePesquisa ?? "Projetos de Pesquisa"}
9-
</h1>
10-
<p class="text-base-content mb-4">
11-
{iniciativas?.descricaoProjetosDePesquisa ??
12-
"Projetos desenvolvidos por docentes e associados ao CPPS, com apoio de agências de fomento."}
13-
</p>
14-
15-
<!-- Lista de projetos sem ordenação -->
16-
<div class="space-y-4">
17-
{projetos.map((proj, index) => (
18-
<details class="border border-base-300 rounded-xl p-4 group">
19-
<summary class="cursor-pointer text-lg font-semibold text-primary group-open:mb-4">
20-
{proj.titulo} — <span class="text-base-content">{proj.docente}</span>
21-
<span class="text-sm text-neutral-500">({proj.periodo})</span>
22-
</summary>
23-
<div class="space-y-2 mt-2 text-base-content">
24-
<p><strong>Agência:</strong> {proj.agencia}</p>
25-
<p><strong>Processo:</strong> {proj.processo}</p>
26-
<p><strong>Natureza:</strong> {proj.natureza}</p>
27-
<p><strong>Valor:</strong> {proj.valor}</p>
28-
<p><strong>Pesquisadores Associados:</strong> {proj.associados}</p>
29-
<p><strong>Resumo:</strong> {proj.resumo}</p>
30-
{Array.isArray(proj.apoioCentro) && proj.apoioCentro.length > 0 && (
31-
<div>
32-
<strong>Apoios do CPPS:</strong>
33-
<ul class="list-disc list-inside ml-4">
34-
{proj.apoioCentro.map((item) => (
35-
<li>{item}</li>
36-
))}
37-
</ul>
50+
<!-- Cabeçalho -->
51+
<div class="text-center mb-8">
52+
<h1 class="text-4xl font-bold text-primary mb-4">
53+
{iniciativas?.projetosDePesquisa ?? "Projetos de Pesquisa"}
54+
</h1>
55+
<p class="text-lg text-base-content max-w-3xl mx-auto">
56+
{iniciativas?.descricaoProjetosDePesquisa ?? "Projetos desenvolvidos por docentes e associados ao CPPS."}
57+
</p>
58+
</div>
59+
60+
<!-- Estatísticas -->
61+
<div class="stats shadow w-full mb-8">
62+
<div class="stat">
63+
<div class="stat-title">Total de Projetos</div>
64+
<div class="stat-value text-primary">{projetosOrdenados.length}</div>
65+
</div>
66+
<div class="stat">
67+
<div class="stat-title">Ordenação Atual</div>
68+
<div class="stat-value text-sm">
69+
{ordem === 'titulo' ? 'Por Título' :
70+
ordem === 'docente' ? 'Por Docente' :
71+
'Por Período'}
72+
</div>
73+
</div>
74+
</div>
75+
76+
<!-- Seletor de ordenação melhorado -->
77+
<div class="flex flex-wrap gap-4 items-center justify-between mb-8 p-4 bg-base-200 rounded-lg">
78+
<div class="flex items-center gap-2">
79+
<span class="font-semibold text-base-content">
80+
{iniciativas?.ordenarPor ?? "Ordenar por"}:
81+
</span>
82+
<div class="btn-group">
83+
<button
84+
class={`btn btn-sm ${ordem === 'titulo' ? 'btn-active btn-primary' : 'btn-outline'}`}
85+
onclick="ordenarProjetos('titulo')"
86+
>
87+
{iniciativas?.porTitulo ?? "Título"}
88+
</button>
89+
<button
90+
class={`btn btn-sm ${ordem === 'docente' ? 'btn-active btn-primary' : 'btn-outline'}`}
91+
onclick="ordenarProjetos('docente')"
92+
>
93+
{iniciativas?.porDocente ?? "Docente"}
94+
</button>
95+
<button
96+
class={`btn btn-sm ${ordem === 'periodo' ? 'btn-active btn-primary' : 'btn-outline'}`}
97+
onclick="ordenarProjetos('periodo')"
98+
>
99+
{iniciativas?.porPeriodo ?? "Período"}
100+
</button>
101+
</div>
102+
</div>
103+
104+
<!-- Filtro adicional -->
105+
<div class="flex items-center gap-2">
106+
<span class="font-semibold text-base-content">Filtrar:</span>
107+
<select class="select select-bordered select-sm" id="filtro-agencia">
108+
<option value="">Todas as Agências</option>
109+
<option value="FAPESP">FAPESP</option>
110+
<option value="CNPq">CNPq</option>
111+
<option value="CAPES">CAPES</option>
112+
</select>
113+
</div>
114+
</div>
115+
116+
<!-- Lista de projetos melhorada -->
117+
<div id="lista-projetos" class="space-y-6">
118+
{projetosOrdenados.map((proj, index) => (
119+
<article class="card bg-base-100 shadow-lg border border-base-300 hover:shadow-xl transition-shadow duration-300" key={index}>
120+
<div class="card-body">
121+
<!-- Cabeçalho do projeto -->
122+
<div class="flex flex-wrap items-start justify-between gap-4 mb-4">
123+
<div class="flex-1">
124+
<div class="flex items-center gap-2 mb-2">
125+
<span class="badge badge-primary badge-sm">#{index + 1}</span>
126+
<span class="badge badge-outline badge-sm">{proj.agencia}</span>
127+
<span class="badge badge-ghost badge-sm">{proj.periodo}</span>
128+
</div>
129+
<h2 class="card-title text-xl text-primary mb-2">
130+
{proj.titulo}
131+
</h2>
132+
<p class="text-base-content font-medium">
133+
<span class="text-sm text-neutral-500">Docente responsável:</span> {proj.docente}
134+
</p>
135+
</div>
136+
<button class="btn btn-circle btn-ghost btn-sm" onclick={`toggleDetails('projeto-${index}')`}>
137+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
138+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
139+
</svg>
140+
</button>
141+
</div>
142+
143+
<!-- Resumo sempre visível -->
144+
<div class="mb-4">
145+
<h3 class="font-semibold text-base-content mb-2">Resumo:</h3>
146+
<p class="text-sm text-base-content/80 line-clamp-3">
147+
{proj.resumo}
148+
</p>
149+
</div>
150+
151+
<!-- Detalhes expansíveis -->
152+
<div id={`projeto-${index}`} class="hidden space-y-4 pt-4 border-t border-base-300">
153+
<div class="grid md:grid-cols-2 gap-4">
154+
<div class="space-y-2">
155+
<p><strong class="text-primary">Processo:</strong> {proj.processo}</p>
156+
<p><strong class="text-primary">Natureza:</strong> {proj.natureza}</p>
157+
<p><strong class="text-primary">Valor:</strong> {proj.valor}</p>
158+
</div>
159+
<div class="space-y-2">
160+
<p><strong class="text-primary">Pesquisadores Associados:</strong> {proj.associados}</p>
161+
</div>
38162
</div>
39-
)}
163+
164+
{Array.isArray(proj.apoioCentro) && proj.apoioCentro.length > 0 && (
165+
<div class="mt-4">
166+
<h4 class="font-semibold text-primary mb-2">Apoios do CPPS:</h4>
167+
<ul class="list-disc list-inside space-y-1 text-sm">
168+
{proj.apoioCentro.map((item, i) => (
169+
<li key={i} class="text-base-content/80">{item}</li>
170+
))}
171+
</ul>
172+
</div>
173+
)}
174+
</div>
40175
</div>
41-
</details>
176+
</article>
42177
))}
43178
</div>
179+
180+
<!-- Mensagem quando não há projetos -->
181+
{projetosOrdenados.length === 0 && (
182+
<div class="text-center py-12">
183+
<div class="text-6xl mb-4">📚</div>
184+
<h3 class="text-xl font-semibold text-base-content mb-2">Nenhum projeto encontrado</h3>
185+
<p class="text-base-content/60">Não há projetos disponíveis no momento.</p>
186+
</div>
187+
)}
44188
</section>
189+
190+
<!-- Dados para o cliente -->
191+
<script type="application/json" id="projetos-data">
192+
{JSON.stringify(projetosOrdenados)}
193+
</script>
194+
195+
<script is:inline>
196+
// Função para escapar HTML
197+
function escapeHtml(text) {
198+
if (!text) return '';
199+
const div = document.createElement('div');
200+
div.textContent = text;
201+
return div.innerHTML;
202+
}
203+
204+
// Função para alternar detalhes do projeto
205+
function toggleDetails(elementId) {
206+
const element = document.getElementById(elementId);
207+
const button = element?.previousElementSibling?.querySelector('button[onclick*="toggleDetails"]');
208+
209+
if (element) {
210+
element.classList.toggle('hidden');
211+
if (button) {
212+
const svg = button.querySelector('svg');
213+
if (svg) {
214+
svg.style.transform = element.classList.contains('hidden') ? 'rotate(0deg)' : 'rotate(180deg)';
215+
}
216+
}
217+
}
218+
}
219+
220+
// Função para ordenar e recarregar a página
221+
function ordenarProjetos(criterio) {
222+
const url = new URL(window.location);
223+
url.searchParams.set('ordem', criterio);
224+
window.location.href = url.toString(); // 🔁 reload com o novo critério
225+
}
226+
227+
// Função para atualizar visual dos botões (opcional, se quiser manter ativo visualmente)
228+
function atualizarBotoes(criterioAtivo) {
229+
document.querySelectorAll('.btn-group button').forEach(btn => {
230+
const criterio = btn.getAttribute('onclick')?.match(/'([^']+)'/)?.[1];
231+
if (criterio === criterioAtivo) {
232+
btn.className = 'btn btn-sm btn-active btn-primary';
233+
} else {
234+
btn.className = 'btn btn-sm btn-outline';
235+
}
236+
});
237+
}
238+
239+
// Inicialização: destaca o botão correto se houver parâmetro na URL
240+
document.addEventListener('DOMContentLoaded', function() {
241+
const urlParams = new URLSearchParams(window.location.search);
242+
const ordemUrl = urlParams.get('ordem');
243+
const ordemValida = ['titulo', 'docente', 'periodo'];
244+
245+
if (ordemUrl && ordemValida.includes(ordemUrl)) {
246+
atualizarBotoes(ordemUrl);
247+
}
248+
});
249+
250+
// Tornar funções globais
251+
window.toggleDetails = toggleDetails;
252+
window.ordenarProjetos = ordenarProjetos;
253+
</script>
254+
255+
256+
<style>
257+
.line-clamp-3 {
258+
display: -webkit-box;
259+
-webkit-line-clamp: 3;
260+
-webkit-box-orient: vertical;
261+
overflow: hidden;
262+
}
263+
</style>

0 commit comments

Comments
 (0)