Initial commit
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
49
README.md
Normal file
49
README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Plugin Vagas Três Corações
|
||||
|
||||
Este plugin WordPress importa e exibe automaticamente as vagas de emprego publicadas no site da Prefeitura de Três Corações.
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
- Busca automática das vagas diretamente do site oficial.
|
||||
- Atualização automática das vagas apenas 4 vezes ao dia (00:00, 10:00, 18:00, 22:00), reduzindo requisições e otimizando performance.
|
||||
- Exibição das vagas em uma tabela moderna, responsiva e ordenada alfabeticamente.
|
||||
- Shortcode fácil de usar para inserir a tabela em qualquer página ou post.
|
||||
|
||||
## Instalação
|
||||
|
||||
1. Faça upload da pasta do plugin para o diretório `wp-content/plugins` do seu WordPress.
|
||||
2. Ative o plugin no painel do WordPress.
|
||||
|
||||
## Como usar
|
||||
|
||||
Adicione o shortcode abaixo em qualquer página ou post onde deseja exibir as vagas:
|
||||
|
||||
```
|
||||
[vagas_tres_coracoes]
|
||||
```
|
||||
|
||||
## Personalização
|
||||
|
||||
- O plugin já inclui um CSS moderno e responsivo para a tabela de vagas.
|
||||
- Para customizar o visual, edite o arquivo `style.css` dentro da pasta do plugin.
|
||||
|
||||
## Funcionamento do Cache
|
||||
|
||||
- As vagas são atualizadas automaticamente apenas nos horários: 00:00, 10:00, 18:00 e 22:00.
|
||||
- Entre esses horários, o plugin utiliza cache para evitar múltiplas requisições ao site da Prefeitura.
|
||||
|
||||
## Estrutura dos Arquivos
|
||||
|
||||
- `tres-coracoes-vagas.php`: Arquivo principal do plugin.
|
||||
- `includes/functions.php`: Funções de busca, cache e exibição das vagas.
|
||||
- `style.css`: Estilos da tabela de vagas.
|
||||
|
||||
## Observações
|
||||
|
||||
- O plugin busca até 15 páginas de vagas por atualização.
|
||||
- Linhas vazias ou vagas incompletas são automaticamente ignoradas na exibição.
|
||||
- As vagas são ordenadas alfabeticamente pelo nome da vaga.
|
||||
|
||||
## Suporte
|
||||
|
||||
Para dúvidas ou sugestões, entre em contato com o desenvolvedor do plugin.
|
115
includes/functions.php
Normal file
115
includes/functions.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
// Função para buscar vagas de todas as páginas
|
||||
function tc_get_vagas() {
|
||||
$base_url = 'https://trescoracoes.mg.gov.br/empregatrescoracoes/vagas?&pagina=';
|
||||
$page = 1;
|
||||
$vagas = array();
|
||||
$max_pages = 15; // Limite de páginas para evitar loop infinito
|
||||
|
||||
while ($page <= $max_pages) {
|
||||
$url = $base_url . $page;
|
||||
$response = wp_remote_get($url);
|
||||
|
||||
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
|
||||
break;
|
||||
}
|
||||
|
||||
$body = wp_remote_retrieve_body($response);
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($body);
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
// Encontrar a tabela de vagas
|
||||
$rows = $xpath->query("//table[contains(@class, 'table')]/tbody/tr");
|
||||
|
||||
if ($rows->length === 0) {
|
||||
break; // Não há mais vagas
|
||||
}
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$cols = $row->getElementsByTagName('td');
|
||||
if ($cols->length >= 3) {
|
||||
$vaga = trim($cols[0]->textContent);
|
||||
$cidade = trim($cols[1]->textContent);
|
||||
$quantidade = trim($cols[2]->textContent);
|
||||
// Ignora linhas totalmente vazias
|
||||
if ($vaga !== '' || $cidade !== '' || $quantidade !== '') {
|
||||
$vagas[] = array(
|
||||
'vaga' => $vaga,
|
||||
'cidade' => $cidade,
|
||||
'quantidade' => $quantidade
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$page++;
|
||||
}
|
||||
|
||||
// Ordenar vagas por nome da vaga
|
||||
usort($vagas, function($a, $b) {
|
||||
return strcmp($a['vaga'], $b['vaga']);
|
||||
});
|
||||
|
||||
return $vagas;
|
||||
}
|
||||
|
||||
// Função para obter o próximo horário de atualização
|
||||
function tc_get_next_update_time() {
|
||||
$horarios = ['00:00', '10:00', '18:00', '22:00'];
|
||||
$agora = current_time('H:i');
|
||||
$hoje = current_time('Y-m-d');
|
||||
foreach ($horarios as $hora) {
|
||||
if ($agora < $hora) {
|
||||
return strtotime("$hoje $hora:00");
|
||||
}
|
||||
}
|
||||
// Se já passou de 22:00, retorna o próximo dia às 00:00
|
||||
return strtotime("tomorrow 00:00:00");
|
||||
}
|
||||
|
||||
// Shortcode para exibir as vagas
|
||||
function tc_show_vagas_shortcode() {
|
||||
$transient_key = 'tc_vagas_cache';
|
||||
$vagas = get_transient($transient_key);
|
||||
if ($vagas === false) {
|
||||
$vagas = tc_get_vagas();
|
||||
$next_update = tc_get_next_update_time();
|
||||
$expira_em = $next_update - time();
|
||||
if ($expira_em < 60) $expira_em = 60; // Garante pelo menos 1 min
|
||||
set_transient($transient_key, $vagas, $expira_em);
|
||||
}
|
||||
if (empty($vagas)) {
|
||||
return '<p>Nenhuma vaga encontrada no momento.</p>';
|
||||
}
|
||||
|
||||
$output = '<div class="tc-vagas-wrapper"><table class="tc-vagas-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Vaga</th>
|
||||
<th>Cidade</th>
|
||||
<th>Quantidade</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
foreach ($vagas as $vaga) {
|
||||
// Ignora linhas totalmente vazias ou só com espaços
|
||||
if (empty(trim($vaga['vaga'])) && empty(trim($vaga['cidade'])) && empty(trim($vaga['quantidade']))) continue;
|
||||
$output .= sprintf(
|
||||
'<tr>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
</tr>',
|
||||
esc_html($vaga['vaga']),
|
||||
esc_html($vaga['cidade']),
|
||||
esc_html($vaga['quantidade'])
|
||||
);
|
||||
}
|
||||
|
||||
$output .= '</tbody></table></div>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
add_shortcode('tc_vagas', 'tc_show_vagas_shortcode');
|
159
style.css
Normal file
159
style.css
Normal file
@@ -0,0 +1,159 @@
|
||||
/* Estilos atualizados para a tabela de vagas */
|
||||
.tc-vagas-wrapper {
|
||||
max-width: 1000px;
|
||||
margin: 40px auto;
|
||||
background: var(--branco);
|
||||
border-radius: var(--borda-radius);
|
||||
box-shadow: var(--sombra);
|
||||
padding: 30px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.tc-vagas-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin: 0;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
font-size: 1.05em;
|
||||
background: var(--branco);
|
||||
border-radius: var(--borda-radius);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.tc-vagas-table th,
|
||||
.tc-vagas-table td {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
padding: 15px 20px;
|
||||
text-align: left;
|
||||
transition: var(--transicao);
|
||||
}
|
||||
|
||||
.tc-vagas-table th {
|
||||
background: linear-gradient(135deg, var(--azul-principal) 0%, var(--azul-escuro) 100%);
|
||||
color: var(--branco);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.3px;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.9em;
|
||||
border-top: none;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.tc-vagas-table tr:nth-child(even) {
|
||||
background-color: var(--cinza-claro);
|
||||
}
|
||||
|
||||
.tc-vagas-table tr:hover {
|
||||
background: rgba(0, 166, 251, 0.05);
|
||||
}
|
||||
|
||||
.tc-vagas-table tr:hover td {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.tc-vagas-table td {
|
||||
color: var(--preto);
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tc-vagas-table td:first-child {
|
||||
font-weight: 500;
|
||||
color: var(--azul-escuro);
|
||||
}
|
||||
|
||||
.tc-vagas-table td:last-child {
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: var(--azul-principal);
|
||||
}
|
||||
|
||||
/* Efeito de destaque para a coluna de quantidade */
|
||||
.tc-vagas-table td:last-child::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 60%;
|
||||
background: var(--azul-brilhante);
|
||||
border-radius: 3px;
|
||||
opacity: 0;
|
||||
transition: var(--transicao);
|
||||
}
|
||||
|
||||
.tc-vagas-table tr:hover td:last-child::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Badge para vagas urgentes */
|
||||
.vaga-urgente {
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.vaga-urgente::before {
|
||||
content: 'URGENTE';
|
||||
position: absolute;
|
||||
left: -5px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: var(--vermelho);
|
||||
color: white;
|
||||
font-size: 0.7em;
|
||||
font-weight: 700;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 0.8; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0.8; }
|
||||
}
|
||||
|
||||
/* Responsividade */
|
||||
@media (max-width: 768px) {
|
||||
.tc-vagas-wrapper {
|
||||
padding: 15px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.tc-vagas-table th,
|
||||
.tc-vagas-table td {
|
||||
padding: 12px 10px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.tc-vagas-table td:first-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.tc-vagas-wrapper {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
|
||||
.tc-vagas-table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tc-vagas-table th {
|
||||
font-size: 0.85em;
|
||||
padding: 10px 8px;
|
||||
}
|
||||
|
||||
.tc-vagas-table td {
|
||||
padding: 10px 8px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
86
tres-coracoes-vagas.php
Normal file
86
tres-coracoes-vagas.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Vagas Três Corações
|
||||
* Description: Importa e exibe automaticamente as vagas do site da Prefeitura de Três Corações.
|
||||
* Version: 1.0
|
||||
* Author: Marco Antonio Vivas
|
||||
*/
|
||||
|
||||
add_shortcode('vagas_tres_coracoes', 'vtc_exibir_vagas');
|
||||
|
||||
function vtc_enqueue_styles() {
|
||||
wp_register_style('tc-vagas-style', plugin_dir_url(__FILE__) . 'style.css');
|
||||
wp_enqueue_style('tc-vagas-style');
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'vtc_enqueue_styles');
|
||||
|
||||
function vtc_exibir_vagas() {
|
||||
$todas_vagas = [];
|
||||
|
||||
for ($pagina = 1; $pagina <= 10; $pagina++) {
|
||||
$html = wp_remote_get("https://trescoracoes.mg.gov.br/empregatrescoracoes/vagas?&pagina={$pagina}");
|
||||
|
||||
if (is_wp_error($html)) break;
|
||||
|
||||
$body = wp_remote_retrieve_body($html);
|
||||
|
||||
libxml_use_internal_errors(true);
|
||||
$dom = new DOMDocument();
|
||||
$dom->loadHTML($body);
|
||||
libxml_clear_errors();
|
||||
|
||||
$xpath = new DOMXPath($dom);
|
||||
$items = $xpath->query('//div[contains(@class, "home-painel__listagem-item")]');
|
||||
|
||||
if ($items->length === 0) break;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$vaga_node = $xpath->query('.//h2', $item);
|
||||
$cidade_node = $xpath->query('.//div[contains(@class,"subtitulos")]/span[2]', $item);
|
||||
$quantidade_node = $xpath->query('.//div[contains(@class,"descricao")]/span', $item);
|
||||
|
||||
$vaga = $vaga_node->length ? trim($vaga_node[0]->textContent) : '';
|
||||
$cidade = $cidade_node->length ? trim($cidade_node[0]->textContent) : '';
|
||||
$quantidade = $quantidade_node->length ? trim($quantidade_node[0]->textContent) : '';
|
||||
|
||||
// Verifica se a vaga não está vazia antes de adicionar
|
||||
if (!empty($vaga) || !empty($cidade) || !empty($quantidade)) {
|
||||
$todas_vagas[] = [
|
||||
'vaga' => $vaga,
|
||||
'cidade' => $cidade,
|
||||
'quantidade' => $quantidade,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Se não houver vagas, retorna mensagem
|
||||
if (empty($todas_vagas)) {
|
||||
return '<div class="tc-vagas-wrapper"><p>Nenhuma vaga encontrada no momento.</p></div>';
|
||||
}
|
||||
|
||||
$output = '<div class="tc-vagas-wrapper"><table class="tc-vagas-table">';
|
||||
$output .= '<thead><tr><th>Vaga</th><th>Cidade</th><th>Quantidade</th></tr></thead><tbody>';
|
||||
|
||||
foreach ($todas_vagas as $vaga) {
|
||||
// Ignora linhas totalmente vazias (segunda verificação por segurança)
|
||||
if (empty(trim($vaga['vaga'])) && empty(trim($vaga['cidade'])) && empty(trim($vaga['quantidade']))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$output .= sprintf(
|
||||
'<tr>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
</tr>',
|
||||
esc_html($vaga['vaga']),
|
||||
esc_html($vaga['cidade']),
|
||||
esc_html($vaga['quantidade'])
|
||||
);
|
||||
}
|
||||
|
||||
$output .= '</tbody></table></div>';
|
||||
|
||||
return $output;
|
||||
}
|
Reference in New Issue
Block a user