wagtail-enap-designsystem 1.2.1.130__py3-none-any.whl → 1.2.1.131__py3-none-any.whl
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.
Potentially problematic release.
This version of wagtail-enap-designsystem might be problematic. Click here for more details.
- enap_designsystem/context_processors.py +30 -6
- enap_designsystem/migrations/0405_sistemavotacaopage_exigir_recaptcha_and_more.py +41 -0
- enap_designsystem/models.py +83 -48
- enap_designsystem/settings.py +4 -0
- enap_designsystem/templates/enap_designsystem/blocks/recaptcha.html +146 -126
- enap_designsystem/templates/enap_designsystem/form_templates/formulario_page.html +1 -0
- enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +580 -548
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/METADATA +1 -1
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/RECORD +12 -11
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/WHEEL +0 -0
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/licenses/LICENSE +0 -0
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/top_level.txt +0 -0
|
@@ -955,52 +955,63 @@
|
|
|
955
955
|
{% block content %}
|
|
956
956
|
{% load static %}
|
|
957
957
|
<section class="padding-mobile">
|
|
958
|
-
<div class="sistema-votacao-wrapper"
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
{% endfor %}
|
|
969
|
-
{% endif %}>
|
|
970
|
-
<div class="sistema-votacao-header{% if page.imagem_fundo %} has-background{% endif %}"
|
|
971
|
-
{% if page.imagem_fundo %}
|
|
972
|
-
{% for block in page.imagem_fundo %}
|
|
973
|
-
style="background-image: url('{{ block.value.file.url }}'); object-fit: cover; object-position: top;"
|
|
958
|
+
<div class="sistema-votacao-wrapper"
|
|
959
|
+
{% if page.background_image_fundo %}
|
|
960
|
+
{% for block in page.background_image_fundo %}
|
|
961
|
+
{% if block.block_type == 'background_image_stream' and block.value %}
|
|
962
|
+
style="background-image: url('{{ block.value.file.url }}');
|
|
963
|
+
background-size: cover;
|
|
964
|
+
background-position: center;
|
|
965
|
+
background-repeat: no-repeat;
|
|
966
|
+
background-attachment: fixed;"
|
|
967
|
+
{% endif %}
|
|
974
968
|
{% endfor %}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
{{ page.descricao_header|richtext }}
|
|
969
|
+
{% endif %}>
|
|
970
|
+
<div class="sistema-votacao-header{% if page.imagem_fundo %} has-background{% endif %}"
|
|
971
|
+
{% if page.imagem_fundo %}
|
|
972
|
+
{% for block in page.imagem_fundo %}
|
|
973
|
+
style="background-image: url('{{ block.value.file.url }}'); object-fit: cover; object-position: top;"
|
|
974
|
+
{% endfor %}
|
|
975
|
+
{% endif %}>
|
|
976
|
+
<div class="votacao-content">
|
|
977
|
+
<div class="sistema-votacao-icon">
|
|
978
|
+
<i class="fas fa-vote-yea"></i>
|
|
986
979
|
</div>
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
980
|
+
<h1 class="sistema-votacao-title">{{ page.title }}</h1>
|
|
981
|
+
<p class="sistema-votacao-subtitle">{{ page.subtitulo }}</p>
|
|
982
|
+
|
|
983
|
+
{% if page.descricao_header %}
|
|
984
|
+
<div class="sistema-votacao-descricao">
|
|
985
|
+
{{ page.descricao_header|richtext }}
|
|
986
|
+
</div>
|
|
987
|
+
{% endif %}
|
|
988
|
+
</div>
|
|
989
|
+
</div>
|
|
990
990
|
|
|
991
991
|
|
|
992
|
-
{% if page.conteudo_pagina %}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
{% endif %}
|
|
992
|
+
{% if page.conteudo_pagina %}
|
|
993
|
+
{% for block in page.conteudo_pagina %}
|
|
994
|
+
{% include_block block %}
|
|
995
|
+
{% endfor %}
|
|
996
|
+
{% endif %}
|
|
997
997
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
998
|
+
{% if page.exigir_recaptcha %}
|
|
999
|
+
<div class="recaptcha-gate" style="display: block;">
|
|
1000
|
+
<div class="recaptcha-content" style="max-width: 600px; margin: 2rem auto; padding: 2rem; background: white; border-radius: 12px;">
|
|
1001
|
+
<h2>Verificação de Segurança</h2>
|
|
1002
|
+
<p>Para acessar o sistema de votação, confirme que você não é um robô:</p>
|
|
1003
|
+
|
|
1004
|
+
{% include 'enap_designsystem/blocks/recaptcha.html' with value=recaptcha_config %}
|
|
1005
|
+
|
|
1006
|
+
<button type="button" id="prosseguir-votacao" disabled style="margin-top: 1rem; padding: 1rem 2rem; background: #ccc; border: none; border-radius: 50px; width: 100%;">
|
|
1007
|
+
Complete a verificação acima
|
|
1008
|
+
</button>
|
|
1009
|
+
</div>
|
|
1010
|
+
</div>
|
|
1011
|
+
{% endif %}
|
|
1001
1012
|
|
|
1002
1013
|
|
|
1003
|
-
<div class="sistema-votacao-container"
|
|
1014
|
+
<div class="sistema-votacao-container" {% if page.exigir_recaptcha %}style="display: none;"{% endif %}>>
|
|
1004
1015
|
<!-- Header -->
|
|
1005
1016
|
|
|
1006
1017
|
|
|
@@ -1144,82 +1155,82 @@
|
|
|
1144
1155
|
{% endif %}
|
|
1145
1156
|
</div>
|
|
1146
1157
|
</div>
|
|
1147
|
-
</div>
|
|
1158
|
+
</div>
|
|
1148
1159
|
|
|
1149
|
-
<!-- Modal de Conclusão -->
|
|
1150
|
-
<div id="modal-conclusao" class="sistema-modal-conclusao">
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1160
|
+
<!-- Modal de Conclusão -->
|
|
1161
|
+
<div id="modal-conclusao" class="sistema-modal-conclusao">
|
|
1162
|
+
<div class="sistema-modal-conclusao-content">
|
|
1163
|
+
<div class="sistema-conclusao-icon">
|
|
1164
|
+
<i class="fas fa-trophy"></i>
|
|
1165
|
+
</div>
|
|
1166
|
+
<h3 class="sistema-conclusao-title">Parabéns!</h3>
|
|
1167
|
+
<p class="sistema-conclusao-subtitle">Você votou em todas as categorias disponíveis!</p>
|
|
1168
|
+
|
|
1169
|
+
<div class="sistema-conclusao-stats">
|
|
1170
|
+
<div class="sistema-conclusao-stats-title">Sua Participação</div>
|
|
1171
|
+
<div class="sistema-stats-grid">
|
|
1172
|
+
<div class="sistema-stat-item">
|
|
1173
|
+
<span class="sistema-stat-number" id="total-categorias-votadas">{{ total_categorias }}</span>
|
|
1174
|
+
<span class="sistema-stat-label">Categorias</span>
|
|
1175
|
+
</div>
|
|
1176
|
+
<div class="sistema-stat-item">
|
|
1177
|
+
<span class="sistema-stat-number" id="total-projetos-visualizados">-</span>
|
|
1178
|
+
<span class="sistema-stat-label">Projetos</span>
|
|
1179
|
+
</div>
|
|
1168
1180
|
</div>
|
|
1169
1181
|
</div>
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
</
|
|
1182
|
+
|
|
1183
|
+
<div class="sistema-conclusao-actions">
|
|
1184
|
+
<button class="sistema-btn-votar-novamente" onclick="SistemaVotacao.reiniciarVotacao()">
|
|
1185
|
+
<i class="fas fa-redo"></i>
|
|
1186
|
+
Votar Novamente
|
|
1187
|
+
</button>
|
|
1188
|
+
<button class="sistema-btn-encerrar-definitivo" onclick="SistemaVotacao.encerrarDefinitivo()">
|
|
1189
|
+
<i class="fas fa-check"></i>
|
|
1190
|
+
Encerrar
|
|
1191
|
+
</button>
|
|
1192
|
+
</div>
|
|
1181
1193
|
</div>
|
|
1182
1194
|
</div>
|
|
1183
|
-
</div>
|
|
1184
|
-
|
|
1185
|
-
<!-- Modal de Escolha Pós-Voto -->
|
|
1186
|
-
<div id="modal-pos-voto" class="sistema-modal-overlay">
|
|
1187
|
-
<div class="sistema-modal-content">
|
|
1188
|
-
<div class="sistema-modal-header">
|
|
1189
|
-
<h3 class="sistema-modal-title">Voto registrado com sucesso!</h3>
|
|
1190
|
-
</div>
|
|
1191
1195
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
<div class="sistema-
|
|
1195
|
-
<div class="sistema-
|
|
1196
|
-
<
|
|
1197
|
-
<span class="sistema-progresso-status" id="progresso-status-modal">0 de {{ total_categorias }} categorias</span>
|
|
1196
|
+
<!-- Modal de Escolha Pós-Voto -->
|
|
1197
|
+
<div id="modal-pos-voto" class="sistema-modal-overlay">
|
|
1198
|
+
<div class="sistema-modal-content">
|
|
1199
|
+
<div class="sistema-modal-header">
|
|
1200
|
+
<h3 class="sistema-modal-title">Voto registrado com sucesso!</h3>
|
|
1198
1201
|
</div>
|
|
1199
|
-
|
|
1200
|
-
|
|
1202
|
+
|
|
1203
|
+
<!-- Progresso da Votação no Modal -->
|
|
1204
|
+
{% if page.mostrar_progresso and categorias %}
|
|
1205
|
+
<div class="sistema-progresso-section" style="position: static; margin: 1.5rem 0; padding: 1.5rem; right: auto; bottom: auto;">
|
|
1206
|
+
<div class="sistema-progresso-header">
|
|
1207
|
+
<h2 class="sistema-progresso-title">Progresso da Votação</h2>
|
|
1208
|
+
<span class="sistema-progresso-status" id="progresso-status-modal">0 de {{ total_categorias }} categorias</span>
|
|
1209
|
+
</div>
|
|
1210
|
+
<div class="sistema-progresso-bar">
|
|
1211
|
+
<div class="sistema-progresso-fill" id="progresso-fill-modal" style="width: 0%"></div>
|
|
1212
|
+
</div>
|
|
1213
|
+
<p class="sistema-progresso-text" id="progresso-text-modal">0% concluído</p>
|
|
1201
1214
|
</div>
|
|
1202
|
-
|
|
1203
|
-
</div>
|
|
1204
|
-
{% endif %}
|
|
1215
|
+
{% endif %}
|
|
1205
1216
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1217
|
+
|
|
1218
|
+
<div class="sistema-modal-actions">
|
|
1219
|
+
<button class="sistema-btn-continuar" onclick="SistemaVotacao.continuarVotacao()">
|
|
1220
|
+
Votar na próxima categoria
|
|
1221
|
+
<i class="fas fa-arrow-right"></i>
|
|
1222
|
+
</button>
|
|
1223
|
+
<button class="sistema-btn-finalizar" onclick="SistemaVotacao.finalizarVotacao()">
|
|
1224
|
+
<i class="fas fa-check-circle"></i>
|
|
1225
|
+
<span>Finalizar Votação</span>
|
|
1226
|
+
</button>
|
|
1227
|
+
</div>
|
|
1216
1228
|
</div>
|
|
1217
1229
|
</div>
|
|
1218
|
-
</div>
|
|
1219
1230
|
|
|
1220
|
-
<!-- Mensagem de Feedback -->
|
|
1221
|
-
<div id="feedback-message" class="sistema-feedback-message"></div>
|
|
1222
|
-
{% endblock %}
|
|
1231
|
+
<!-- Mensagem de Feedback -->
|
|
1232
|
+
<div id="feedback-message" class="sistema-feedback-message"></div>
|
|
1233
|
+
{% endblock %}
|
|
1223
1234
|
|
|
1224
1235
|
{% block footer %}
|
|
1225
1236
|
{% include "enap_designsystem/includes/footer.html" %}
|
|
@@ -1231,498 +1242,519 @@
|
|
|
1231
1242
|
|
|
1232
1243
|
</section>
|
|
1233
1244
|
<script>
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
categoriasOrdem: [],
|
|
1238
|
-
proximaCategoriaData: null,
|
|
1239
|
-
elementos: {},
|
|
1240
|
-
configuracao: {
|
|
1241
|
-
votacaoAtiva: {% if votacao_ativa %}true{% else %}false{% endif %},
|
|
1242
|
-
totalCategorias: {{ total_categorias|default:0 }},
|
|
1243
|
-
permitirMultiplosVotos: {% if page.permitir_multiplos_votos %}true{% else %}false{% endif %},
|
|
1244
|
-
// URL corrigida - usar path absoluto
|
|
1245
|
-
urlVotar: '/votar/'
|
|
1246
|
-
},
|
|
1247
|
-
|
|
1248
|
-
// Inicialização
|
|
1249
|
-
init() {
|
|
1250
|
-
console.log('🚀 Inicializando Sistema de Votação...');
|
|
1245
|
+
// reCAPTCHA handler
|
|
1246
|
+
window.onRecaptchaSuccess = function(response) {
|
|
1247
|
+
console.log('reCAPTCHA completado');
|
|
1251
1248
|
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const categoriaId = button.getAttribute('data-categoria-id');
|
|
1249
|
+
// Habilitar botão
|
|
1250
|
+
const botao = document.getElementById('prosseguir-votacao');
|
|
1251
|
+
if (botao) {
|
|
1252
|
+
botao.disabled = false;
|
|
1253
|
+
botao.innerHTML = 'Iniciar Votação';
|
|
1254
|
+
botao.style.background = '#007D7A';
|
|
1255
|
+
botao.style.color = 'white';
|
|
1256
|
+
|
|
1257
|
+
// Configurar clique
|
|
1258
|
+
botao.onclick = function() {
|
|
1259
|
+
document.querySelector('.recaptcha-gate').style.display = 'none';
|
|
1260
|
+
document.querySelector('.sistema-votacao-container').style.display = 'block';
|
|
1261
|
+
SistemaVotacao.init();
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1266
|
+
const SistemaVotacao = {
|
|
1267
|
+
// Estado da aplicação
|
|
1268
|
+
votosCategoria: new Set(),
|
|
1269
|
+
categoriasOrdem: [],
|
|
1270
|
+
proximaCategoriaData: null,
|
|
1271
|
+
elementos: {},
|
|
1272
|
+
configuracao: {
|
|
1273
|
+
votacaoAtiva: {% if votacao_ativa %}true{% else %}false{% endif %},
|
|
1274
|
+
totalCategorias: {{ total_categorias|default:0 }},
|
|
1275
|
+
permitirMultiplosVotos: {% if page.permitir_multiplos_votos %}true{% else %}false{% endif %},
|
|
1276
|
+
// URL corrigida - usar path absoluto
|
|
1277
|
+
urlVotar: '/votar/'
|
|
1278
|
+
},
|
|
1279
|
+
|
|
1280
|
+
// Inicialização
|
|
1281
|
+
init() {
|
|
1282
|
+
console.log('🚀 Inicializando Sistema de Votação...');
|
|
1287
1283
|
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1284
|
+
this.cacheElementos();
|
|
1285
|
+
this.configurarTabs();
|
|
1286
|
+
this.configurarCategorias();
|
|
1287
|
+
this.configurarModais();
|
|
1288
|
+
this.configurarCSRF();
|
|
1289
|
+
|
|
1290
|
+
console.log('✅ Sistema inicializado');
|
|
1291
|
+
console.log('📊 Configuração:', this.configuracao);
|
|
1292
|
+
},
|
|
1293
|
+
|
|
1294
|
+
// Cache de elementos DOM
|
|
1295
|
+
cacheElementos() {
|
|
1296
|
+
this.elementos = {
|
|
1297
|
+
tabButtons: document.querySelectorAll('.sistema-tab-button'),
|
|
1298
|
+
tabContents: document.querySelectorAll('.sistema-tab-content'),
|
|
1299
|
+
progressoFill: document.getElementById('progresso-fill'),
|
|
1300
|
+
progressoStatus: document.getElementById('progresso-status'),
|
|
1301
|
+
progressoText: document.querySelector('.sistema-progresso-text'),
|
|
1302
|
+
progressoFillModal: document.getElementById('progresso-fill-modal'),
|
|
1303
|
+
progressoStatusModal: document.getElementById('progresso-status-modal'),
|
|
1304
|
+
progressoTextModal: document.getElementById('progresso-text-modal'),
|
|
1305
|
+
modalPosVoto: document.getElementById('modal-pos-voto'),
|
|
1306
|
+
modalConclusao: document.getElementById('modal-conclusao'),
|
|
1307
|
+
previewProxima: document.getElementById('preview-proxima-categoria'),
|
|
1308
|
+
feedbackMessage: document.getElementById('feedback-message')
|
|
1309
|
+
};
|
|
1310
|
+
|
|
1311
|
+
console.log('DOM Elements cached:', Object.keys(this.elementos).length);
|
|
1312
|
+
},
|
|
1313
|
+
|
|
1314
|
+
// Configurar sistema de tabs
|
|
1315
|
+
configurarTabs() {
|
|
1316
|
+
this.elementos.tabButtons.forEach((button, index) => {
|
|
1317
|
+
const targetId = button.getAttribute('data-tab-target');
|
|
1318
|
+
const categoriaId = button.getAttribute('data-categoria-id');
|
|
1319
|
+
|
|
1320
|
+
button.addEventListener('click', (e) => {
|
|
1321
|
+
e.preventDefault();
|
|
1322
|
+
this.trocarTab(targetId, button);
|
|
1323
|
+
});
|
|
1291
1324
|
});
|
|
1292
|
-
}
|
|
1293
|
-
},
|
|
1325
|
+
},
|
|
1294
1326
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1327
|
+
// Trocar tab ativa
|
|
1328
|
+
trocarTab(targetId, clickedButton) {
|
|
1329
|
+
const targetContent = document.getElementById(targetId);
|
|
1330
|
+
|
|
1331
|
+
if (!targetContent) {
|
|
1332
|
+
console.error('❌ Conteúdo não encontrado:', targetId);
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1303
1335
|
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1336
|
+
// Remover active de todos
|
|
1337
|
+
this.elementos.tabButtons.forEach(btn => btn.classList.remove('active'));
|
|
1338
|
+
this.elementos.tabContents.forEach(content => content.classList.remove('active'));
|
|
1307
1339
|
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1340
|
+
// Ativar clicado
|
|
1341
|
+
clickedButton.classList.add('active');
|
|
1342
|
+
targetContent.classList.add('active');
|
|
1311
1343
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
}
|
|
1318
|
-
}, 100);
|
|
1319
|
-
},
|
|
1320
|
-
|
|
1321
|
-
// Configurar categorias
|
|
1322
|
-
configurarCategorias() {
|
|
1323
|
-
this.elementos.tabButtons.forEach(button => {
|
|
1324
|
-
const categoriaId = parseInt(button.getAttribute('data-categoria-id'));
|
|
1325
|
-
const iconElement = button.querySelector('i');
|
|
1326
|
-
|
|
1327
|
-
this.categoriasOrdem.push({
|
|
1328
|
-
id: categoriaId,
|
|
1329
|
-
nome: button.textContent.trim(),
|
|
1330
|
-
icone: iconElement ? iconElement.className : 'fas fa-folder'
|
|
1331
|
-
});
|
|
1332
|
-
});
|
|
1333
|
-
},
|
|
1334
|
-
|
|
1335
|
-
// Configurar modais
|
|
1336
|
-
configurarModais() {
|
|
1337
|
-
if (this.elementos.modalPosVoto) {
|
|
1338
|
-
this.elementos.modalPosVoto.addEventListener('click', (e) => {
|
|
1339
|
-
if (e.target === this.elementos.modalPosVoto) {
|
|
1340
|
-
this.pararVotacao();
|
|
1341
|
-
}
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
if (this.elementos.modalConclusao) {
|
|
1346
|
-
this.elementos.modalConclusao.addEventListener('click', (e) => {
|
|
1347
|
-
if (e.target === this.elementos.modalConclusao) {
|
|
1348
|
-
this.encerrarDefinitivo();
|
|
1344
|
+
// Scroll suave
|
|
1345
|
+
setTimeout(() => {
|
|
1346
|
+
const header = targetContent.querySelector('.sistema-categoria-header');
|
|
1347
|
+
if (header) {
|
|
1348
|
+
header.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1349
1349
|
}
|
|
1350
|
+
}, 100);
|
|
1351
|
+
},
|
|
1352
|
+
|
|
1353
|
+
// Configurar categorias
|
|
1354
|
+
configurarCategorias() {
|
|
1355
|
+
this.elementos.tabButtons.forEach(button => {
|
|
1356
|
+
const categoriaId = parseInt(button.getAttribute('data-categoria-id'));
|
|
1357
|
+
const iconElement = button.querySelector('i');
|
|
1358
|
+
|
|
1359
|
+
this.categoriasOrdem.push({
|
|
1360
|
+
id: categoriaId,
|
|
1361
|
+
nome: button.textContent.trim(),
|
|
1362
|
+
icone: iconElement ? iconElement.className : 'fas fa-folder'
|
|
1363
|
+
});
|
|
1350
1364
|
});
|
|
1351
|
-
}
|
|
1352
|
-
},
|
|
1365
|
+
},
|
|
1353
1366
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1367
|
+
// Configurar modais
|
|
1368
|
+
configurarModais() {
|
|
1369
|
+
if (this.elementos.modalPosVoto) {
|
|
1370
|
+
this.elementos.modalPosVoto.addEventListener('click', (e) => {
|
|
1371
|
+
if (e.target === this.elementos.modalPosVoto) {
|
|
1372
|
+
this.pararVotacao();
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
if (this.elementos.modalConclusao) {
|
|
1378
|
+
this.elementos.modalConclusao.addEventListener('click', (e) => {
|
|
1379
|
+
if (e.target === this.elementos.modalConclusao) {
|
|
1380
|
+
this.encerrarDefinitivo();
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
},
|
|
1361
1385
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
}
|
|
1386
|
+
// Configurar CSRF Token
|
|
1387
|
+
configurarCSRF() {
|
|
1388
|
+
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]');
|
|
1389
|
+
if (!csrfToken) {
|
|
1390
|
+
console.warn('⚠️ CSRF token não encontrado');
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1370
1393
|
|
|
1371
|
-
//
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1394
|
+
// FUNÇÃO PRINCIPAL DE VOTAÇÃO - CORRIGIDA
|
|
1395
|
+
async votar(projetoId, categoriaId, button) {
|
|
1396
|
+
console.log('🗳️ Iniciando votação...', { projetoId, categoriaId });
|
|
1397
|
+
|
|
1398
|
+
if (!this.configuracao.votacaoAtiva) {
|
|
1399
|
+
this.showFeedback('Votação não está ativa no momento.', 'error');
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1376
1402
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1403
|
+
// Verificar se botão já foi usado
|
|
1404
|
+
if (button.classList.contains('votado') || button.disabled) {
|
|
1405
|
+
this.showFeedback('Você já votou neste projeto.', 'warning');
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1379
1408
|
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
const dados = {
|
|
1383
|
-
projeto_id: parseInt(projetoId),
|
|
1384
|
-
categoria_id: parseInt(categoriaId)
|
|
1385
|
-
};
|
|
1409
|
+
// Estado de loading
|
|
1410
|
+
this.setLoadingState(button, true);
|
|
1386
1411
|
|
|
1387
|
-
|
|
1412
|
+
try {
|
|
1413
|
+
// Preparar dados
|
|
1414
|
+
const dados = {
|
|
1415
|
+
projeto_id: parseInt(projetoId),
|
|
1416
|
+
categoria_id: parseInt(categoriaId)
|
|
1417
|
+
};
|
|
1418
|
+
|
|
1419
|
+
console.log('📤 Enviando dados:', dados);
|
|
1420
|
+
|
|
1421
|
+
// Headers da requisição
|
|
1422
|
+
const headers = {
|
|
1423
|
+
'Content-Type': 'application/json',
|
|
1424
|
+
};
|
|
1425
|
+
|
|
1426
|
+
// Adicionar CSRF token se disponível
|
|
1427
|
+
const csrfToken = this.getCsrfToken();
|
|
1428
|
+
if (csrfToken) {
|
|
1429
|
+
headers['X-CSRFToken'] = csrfToken;
|
|
1430
|
+
}
|
|
1388
1431
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1432
|
+
// Fazer requisição
|
|
1433
|
+
const response = await fetch(this.configuracao.urlVotar, {
|
|
1434
|
+
method: 'POST',
|
|
1435
|
+
headers: headers,
|
|
1436
|
+
body: JSON.stringify(dados),
|
|
1437
|
+
credentials: 'same-origin'
|
|
1438
|
+
});
|
|
1393
1439
|
|
|
1394
|
-
|
|
1395
|
-
const csrfToken = this.getCsrfToken();
|
|
1396
|
-
if (csrfToken) {
|
|
1397
|
-
headers['X-CSRFToken'] = csrfToken;
|
|
1398
|
-
}
|
|
1440
|
+
console.log('📥 Response status:', response.status);
|
|
1399
1441
|
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
body: JSON.stringify(dados),
|
|
1405
|
-
credentials: 'same-origin'
|
|
1406
|
-
});
|
|
1442
|
+
// Verificar se response é válido
|
|
1443
|
+
if (!response.ok) {
|
|
1444
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1445
|
+
}
|
|
1407
1446
|
|
|
1408
|
-
|
|
1447
|
+
// Parse do JSON
|
|
1448
|
+
let data;
|
|
1449
|
+
try {
|
|
1450
|
+
data = await response.json();
|
|
1451
|
+
console.log('📊 Response data:', data);
|
|
1452
|
+
} catch (parseError) {
|
|
1453
|
+
console.error('❌ Erro ao fazer parse do JSON:', parseError);
|
|
1454
|
+
throw new Error('Resposta inválida do servidor');
|
|
1455
|
+
}
|
|
1409
1456
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1457
|
+
if (data.success) {
|
|
1458
|
+
this.processarVotoSucesso(projetoId, categoriaId, button, data);
|
|
1459
|
+
} else {
|
|
1460
|
+
throw new Error(data.message || 'Erro desconhecido ao registrar voto');
|
|
1461
|
+
}
|
|
1414
1462
|
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
console.log('📊 Response data:', data);
|
|
1420
|
-
} catch (parseError) {
|
|
1421
|
-
console.error('❌ Erro ao fazer parse do JSON:', parseError);
|
|
1422
|
-
throw new Error('Resposta inválida do servidor');
|
|
1463
|
+
} catch (error) {
|
|
1464
|
+
console.error('❌ Erro completo:', error);
|
|
1465
|
+
this.showFeedback(`Erro: ${error.message}`, 'error');
|
|
1466
|
+
this.setLoadingState(button, false);
|
|
1423
1467
|
}
|
|
1468
|
+
},
|
|
1424
1469
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1470
|
+
// Processar voto bem-sucedido
|
|
1471
|
+
processarVotoSucesso(projetoId, categoriaId, button, data) {
|
|
1472
|
+
console.log('✅ Voto processado com sucesso:', data);
|
|
1473
|
+
|
|
1474
|
+
// Atualizar visual do botão
|
|
1475
|
+
button.classList.add('votado');
|
|
1476
|
+
button.innerHTML = `
|
|
1477
|
+
<i class="fas fa-check-circle"></i>
|
|
1478
|
+
Voto registrado!
|
|
1479
|
+
`;
|
|
1480
|
+
button.disabled = true;
|
|
1481
|
+
|
|
1482
|
+
// Atualizar contador se existir
|
|
1483
|
+
this.atualizarContador(projetoId, data.total_votos);
|
|
1484
|
+
|
|
1485
|
+
// Marcar categoria como votada
|
|
1486
|
+
this.votosCategoria.add(parseInt(categoriaId));
|
|
1487
|
+
this.atualizarProgresso();
|
|
1488
|
+
|
|
1489
|
+
// Desabilitar outros botões da categoria se necessário
|
|
1490
|
+
if (!this.configuracao.permitirMultiplosVotos) {
|
|
1491
|
+
this.desabilitarOutrosBotoes(categoriaId, button);
|
|
1429
1492
|
}
|
|
1430
|
-
|
|
1431
|
-
} catch (error) {
|
|
1432
|
-
console.error('❌ Erro completo:', error);
|
|
1433
|
-
this.showFeedback(`Erro: ${error.message}`, 'error');
|
|
1434
|
-
this.setLoadingState(button, false);
|
|
1435
|
-
}
|
|
1436
|
-
},
|
|
1437
|
-
|
|
1438
|
-
// Processar voto bem-sucedido
|
|
1439
|
-
processarVotoSucesso(projetoId, categoriaId, button, data) {
|
|
1440
|
-
console.log('✅ Voto processado com sucesso:', data);
|
|
1441
|
-
|
|
1442
|
-
// Atualizar visual do botão
|
|
1443
|
-
button.classList.add('votado');
|
|
1444
|
-
button.innerHTML = `
|
|
1445
|
-
<i class="fas fa-check-circle"></i>
|
|
1446
|
-
Voto registrado!
|
|
1447
|
-
`;
|
|
1448
|
-
button.disabled = true;
|
|
1449
|
-
|
|
1450
|
-
// Atualizar contador se existir
|
|
1451
|
-
this.atualizarContador(projetoId, data.total_votos);
|
|
1452
|
-
|
|
1453
|
-
// Marcar categoria como votada
|
|
1454
|
-
this.votosCategoria.add(parseInt(categoriaId));
|
|
1455
|
-
this.atualizarProgresso();
|
|
1456
|
-
|
|
1457
|
-
// Desabilitar outros botões da categoria se necessário
|
|
1458
|
-
if (!this.configuracao.permitirMultiplosVotos) {
|
|
1459
|
-
this.desabilitarOutrosBotoes(categoriaId, button);
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
// Mostrar feedback
|
|
1463
|
-
this.showFeedback(`Voto registrado em "${data.projeto_titulo || 'projeto'}"!`, 'success');
|
|
1464
|
-
|
|
1465
|
-
// Mostrar próximo passo após delay
|
|
1466
|
-
setTimeout(() => {
|
|
1467
|
-
this.mostrarModalPosVoto(categoriaId);
|
|
1468
|
-
}, 2000);
|
|
1469
|
-
},
|
|
1470
|
-
|
|
1471
|
-
// Atualizar contador de votos
|
|
1472
|
-
atualizarContador(projetoId, totalVotos) {
|
|
1473
|
-
const contadorElement = document.getElementById(`votos-${projetoId}`);
|
|
1474
|
-
if (contadorElement) {
|
|
1475
|
-
const novoTotal = totalVotos || 1;
|
|
1476
|
-
contadorElement.textContent = novoTotal;
|
|
1477
1493
|
|
|
1478
|
-
//
|
|
1479
|
-
|
|
1480
|
-
contadorElement.style.color = '#28a745';
|
|
1494
|
+
// Mostrar feedback
|
|
1495
|
+
this.showFeedback(`Voto registrado em "${data.projeto_titulo || 'projeto'}"!`, 'success');
|
|
1481
1496
|
|
|
1497
|
+
// Mostrar próximo passo após delay
|
|
1482
1498
|
setTimeout(() => {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1499
|
+
this.mostrarModalPosVoto(categoriaId);
|
|
1500
|
+
}, 2000);
|
|
1501
|
+
},
|
|
1502
|
+
|
|
1503
|
+
// Atualizar contador de votos
|
|
1504
|
+
atualizarContador(projetoId, totalVotos) {
|
|
1505
|
+
const contadorElement = document.getElementById(`votos-${projetoId}`);
|
|
1506
|
+
if (contadorElement) {
|
|
1507
|
+
const novoTotal = totalVotos || 1;
|
|
1508
|
+
contadorElement.textContent = novoTotal;
|
|
1509
|
+
|
|
1510
|
+
// Animação
|
|
1511
|
+
contadorElement.style.transform = 'scale(1.2)';
|
|
1512
|
+
contadorElement.style.color = '#28a745';
|
|
1513
|
+
|
|
1514
|
+
setTimeout(() => {
|
|
1515
|
+
contadorElement.style.transform = 'scale(1)';
|
|
1516
|
+
contadorElement.style.color = '';
|
|
1517
|
+
}, 500);
|
|
1518
|
+
}
|
|
1519
|
+
},
|
|
1520
|
+
|
|
1521
|
+
// Desabilitar outros botões da categoria
|
|
1522
|
+
desabilitarOutrosBotoes(categoriaId, buttonAtivo) {
|
|
1523
|
+
const categorySection = document.getElementById(`categoria-${categoriaId}`);
|
|
1524
|
+
if (categorySection) {
|
|
1525
|
+
const outrosBotoes = categorySection.querySelectorAll('.sistema-btn-votar');
|
|
1526
|
+
outrosBotoes.forEach(btn => {
|
|
1527
|
+
if (btn !== buttonAtivo && !btn.classList.contains('votado')) {
|
|
1528
|
+
btn.disabled = true;
|
|
1529
|
+
btn.classList.add('disabled');
|
|
1530
|
+
btn.innerHTML = `
|
|
1531
|
+
<i class="fas fa-ban"></i>
|
|
1532
|
+
Você já votou nesta categoria
|
|
1533
|
+
`;
|
|
1534
|
+
}
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
},
|
|
1538
|
+
|
|
1539
|
+
// Estado de loading do botão
|
|
1540
|
+
setLoadingState(button, loading) {
|
|
1541
|
+
if (loading) {
|
|
1542
|
+
button.classList.add('loading');
|
|
1543
|
+
button.disabled = true;
|
|
1544
|
+
button.innerHTML = `
|
|
1545
|
+
<i class="fas fa-spinner fa-spin"></i>
|
|
1546
|
+
Votando...
|
|
1547
|
+
`;
|
|
1548
|
+
} else if (!button.classList.contains('votado')) {
|
|
1549
|
+
button.classList.remove('loading');
|
|
1550
|
+
button.disabled = false;
|
|
1551
|
+
button.innerHTML = 'Votar neste Projeto';
|
|
1552
|
+
}
|
|
1553
|
+
},
|
|
1522
1554
|
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
if (proximoIndice < this.categoriasOrdem.length) {
|
|
1529
|
-
this.proximaCategoriaData = this.categoriasOrdem[proximoIndice];
|
|
1530
|
-
this.gerarPreviewProximaCategoria(this.proximaCategoriaData.id);
|
|
1555
|
+
// Mostrar modal pós-voto
|
|
1556
|
+
mostrarModalPosVoto(categoriaAtualId) {
|
|
1557
|
+
const indiceAtual = this.categoriasOrdem.findIndex(cat => cat.id === parseInt(categoriaAtualId));
|
|
1558
|
+
const proximoIndice = indiceAtual + 1;
|
|
1531
1559
|
|
|
1532
|
-
if (this.
|
|
1533
|
-
this.
|
|
1560
|
+
if (proximoIndice < this.categoriasOrdem.length) {
|
|
1561
|
+
this.proximaCategoriaData = this.categoriasOrdem[proximoIndice];
|
|
1562
|
+
this.gerarPreviewProximaCategoria(this.proximaCategoriaData.id);
|
|
1563
|
+
|
|
1564
|
+
if (this.elementos.modalPosVoto) {
|
|
1565
|
+
this.elementos.modalPosVoto.classList.add('show');
|
|
1566
|
+
}
|
|
1567
|
+
} else {
|
|
1568
|
+
this.mostrarModalConclusao();
|
|
1534
1569
|
}
|
|
1535
|
-
}
|
|
1536
|
-
this.mostrarModalConclusao();
|
|
1537
|
-
}
|
|
1538
|
-
},
|
|
1570
|
+
},
|
|
1539
1571
|
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
let previewHTML = '';
|
|
1546
|
-
|
|
1547
|
-
if (projetos.length > 0) {
|
|
1548
|
-
const categoriaInfo = this.categoriasOrdem.find(cat => cat.id === proximaCategoriaId);
|
|
1572
|
+
// Gerar preview da próxima categoria
|
|
1573
|
+
gerarPreviewProximaCategoria(proximaCategoriaId) {
|
|
1574
|
+
const proximaCategoria = document.getElementById(`categoria-${proximaCategoriaId}`);
|
|
1575
|
+
const projetos = proximaCategoria ? proximaCategoria.querySelectorAll('.sistema-projeto-card') : [];
|
|
1549
1576
|
|
|
1550
|
-
previewHTML =
|
|
1551
|
-
<div class="sistema-preview-header">
|
|
1552
|
-
<div class="sistema-preview-icon">
|
|
1553
|
-
<i class="${categoriaInfo.icone}"></i>
|
|
1554
|
-
</div>
|
|
1555
|
-
<h4 class="sistema-preview-title">Próxima Categoria: ${categoriaInfo.nome}</h4>
|
|
1556
|
-
</div>
|
|
1557
|
-
<div class="sistema-preview-projetos">
|
|
1558
|
-
`;
|
|
1577
|
+
let previewHTML = '';
|
|
1559
1578
|
|
|
1560
|
-
projetos.
|
|
1561
|
-
const
|
|
1562
|
-
const equipe = projeto.querySelector('.sistema-equipe-nome')?.textContent || 'Equipe';
|
|
1579
|
+
if (projetos.length > 0) {
|
|
1580
|
+
const categoriaInfo = this.categoriasOrdem.find(cat => cat.id === proximaCategoriaId);
|
|
1563
1581
|
|
|
1564
|
-
previewHTML
|
|
1565
|
-
<div class="sistema-preview-
|
|
1566
|
-
<div class="sistema-preview-
|
|
1567
|
-
|
|
1582
|
+
previewHTML = `
|
|
1583
|
+
<div class="sistema-preview-header">
|
|
1584
|
+
<div class="sistema-preview-icon">
|
|
1585
|
+
<i class="${categoriaInfo.icone}"></i>
|
|
1586
|
+
</div>
|
|
1587
|
+
<h4 class="sistema-preview-title">Próxima Categoria: ${categoriaInfo.nome}</h4>
|
|
1568
1588
|
</div>
|
|
1589
|
+
<div class="sistema-preview-projetos">
|
|
1569
1590
|
`;
|
|
1570
|
-
|
|
1591
|
+
|
|
1592
|
+
projetos.forEach(projeto => {
|
|
1593
|
+
const titulo = projeto.querySelector('.sistema-projeto-title')?.textContent || 'Projeto';
|
|
1594
|
+
const equipe = projeto.querySelector('.sistema-equipe-nome')?.textContent || 'Equipe';
|
|
1595
|
+
|
|
1596
|
+
previewHTML += `
|
|
1597
|
+
<div class="sistema-preview-projeto">
|
|
1598
|
+
<div class="sistema-preview-projeto-titulo">${titulo}</div>
|
|
1599
|
+
<div class="sistema-preview-projeto-equipe">por ${equipe}</div>
|
|
1600
|
+
</div>
|
|
1601
|
+
`;
|
|
1602
|
+
});
|
|
1603
|
+
|
|
1604
|
+
previewHTML += `</div>`;
|
|
1605
|
+
}
|
|
1571
1606
|
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
this.elementos.previewProxima.innerHTML = previewHTML;
|
|
1577
|
-
}
|
|
1578
|
-
},
|
|
1607
|
+
if (this.elementos.previewProxima) {
|
|
1608
|
+
this.elementos.previewProxima.innerHTML = previewHTML;
|
|
1609
|
+
}
|
|
1610
|
+
},
|
|
1579
1611
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
if (this.proximaCategoriaData) {
|
|
1587
|
-
const proximaTab = document.querySelector(`[data-categoria-id="${this.proximaCategoriaData.id}"]`);
|
|
1588
|
-
if (proximaTab) {
|
|
1589
|
-
proximaTab.click();
|
|
1612
|
+
// Continuar votação
|
|
1613
|
+
continuarVotacao() {
|
|
1614
|
+
if (this.elementos.modalPosVoto) {
|
|
1615
|
+
this.elementos.modalPosVoto.classList.remove('show');
|
|
1590
1616
|
}
|
|
1591
|
-
|
|
1592
|
-
|
|
1617
|
+
|
|
1618
|
+
if (this.proximaCategoriaData) {
|
|
1619
|
+
const proximaTab = document.querySelector(`[data-categoria-id="${this.proximaCategoriaData.id}"]`);
|
|
1620
|
+
if (proximaTab) {
|
|
1621
|
+
proximaTab.click();
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
},
|
|
1593
1625
|
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1626
|
+
// Parar votação
|
|
1627
|
+
pararVotacao() {
|
|
1628
|
+
if (this.elementos.modalPosVoto) {
|
|
1629
|
+
this.elementos.modalPosVoto.classList.remove('show');
|
|
1630
|
+
}
|
|
1631
|
+
this.showFeedback('Obrigado pela sua participação!', 'success');
|
|
1632
|
+
},
|
|
1601
1633
|
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1634
|
+
// Mostrar modal de conclusão
|
|
1635
|
+
mostrarModalConclusao() {
|
|
1636
|
+
if (this.elementos.modalConclusao) {
|
|
1637
|
+
this.elementos.modalConclusao.classList.add('show');
|
|
1638
|
+
}
|
|
1639
|
+
},
|
|
1608
1640
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1641
|
+
// Reiniciar votação
|
|
1642
|
+
reiniciarVotacao() {
|
|
1643
|
+
if (this.elementos.modalConclusao) {
|
|
1644
|
+
this.elementos.modalConclusao.classList.remove('show');
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
// Reset estado
|
|
1648
|
+
this.votosCategoria.clear();
|
|
1649
|
+
this.proximaCategoriaData = null;
|
|
1650
|
+
|
|
1651
|
+
// Reset botões
|
|
1652
|
+
const botoesVotar = document.querySelectorAll('.sistema-btn-votar');
|
|
1653
|
+
botoesVotar.forEach(botao => {
|
|
1654
|
+
botao.classList.remove('votado', 'loading', 'disabled');
|
|
1655
|
+
botao.disabled = false;
|
|
1656
|
+
botao.textContent = 'Votar neste Projeto';
|
|
1657
|
+
});
|
|
1658
|
+
|
|
1659
|
+
this.atualizarProgresso();
|
|
1660
|
+
|
|
1661
|
+
const primeiraTab = document.querySelector('.sistema-tab-button');
|
|
1662
|
+
if (primeiraTab) {
|
|
1663
|
+
primeiraTab.click();
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
this.showFeedback('Nova votação iniciada!', 'success');
|
|
1667
|
+
},
|
|
1636
1668
|
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1669
|
+
// Encerrar definitivo
|
|
1670
|
+
encerrarDefinitivo() {
|
|
1671
|
+
if (this.elementos.modalConclusao) {
|
|
1672
|
+
this.elementos.modalConclusao.classList.remove('show');
|
|
1673
|
+
}
|
|
1674
|
+
this.showFeedback('Obrigado pela sua participação!', 'success');
|
|
1675
|
+
},
|
|
1676
|
+
|
|
1677
|
+
// Finalizar votação
|
|
1678
|
+
finalizarVotacao() {
|
|
1679
|
+
if (this.votosCategoria.size === 0) {
|
|
1680
|
+
this.showFeedback('Você ainda não votou em nenhuma categoria.', 'warning');
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
const categoriasRestantes = this.configuracao.totalCategorias - this.votosCategoria.size;
|
|
1685
|
+
|
|
1686
|
+
let mensagem = 'Tem certeza que deseja finalizar sua votação?';
|
|
1687
|
+
if (categoriasRestantes > 0) {
|
|
1688
|
+
mensagem += `\n\nAinda há ${categoriasRestantes} categoria${categoriasRestantes > 1 ? 's' : ''} disponíveis.`;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
if (confirm(mensagem)) {
|
|
1692
|
+
this.showFeedback('Obrigado pela participação! Recarregando...', 'success');
|
|
1693
|
+
setTimeout(() => window.location.reload(), 1500);
|
|
1694
|
+
}
|
|
1695
|
+
},
|
|
1664
1696
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1697
|
+
// Atualizar progresso
|
|
1698
|
+
atualizarProgresso() {
|
|
1699
|
+
const votadas = this.votosCategoria.size;
|
|
1700
|
+
const percentual = Math.round((votadas / this.configuracao.totalCategorias) * 100);
|
|
1701
|
+
|
|
1702
|
+
// Atualizar elementos de progresso
|
|
1703
|
+
const elementos = [
|
|
1704
|
+
{ fill: this.elementos.progressoFill, status: this.elementos.progressoStatus, text: this.elementos.progressoText },
|
|
1705
|
+
{ fill: this.elementos.progressoFillModal, status: this.elementos.progressoStatusModal, text: this.elementos.progressoTextModal }
|
|
1706
|
+
];
|
|
1707
|
+
|
|
1708
|
+
elementos.forEach(({ fill, status, text }) => {
|
|
1709
|
+
if (fill) fill.style.width = `${percentual}%`;
|
|
1710
|
+
if (status) status.textContent = `${votadas} de ${this.configuracao.totalCategorias} categorias`;
|
|
1711
|
+
if (text) text.textContent = `${percentual}% concluído`;
|
|
1712
|
+
});
|
|
1713
|
+
},
|
|
1714
|
+
|
|
1715
|
+
// Mostrar feedback
|
|
1716
|
+
showFeedback(message, type = 'success') {
|
|
1717
|
+
if (!this.elementos.feedbackMessage) {
|
|
1718
|
+
console.log(`Feedback: ${message} (${type})`);
|
|
1719
|
+
return;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
this.elementos.feedbackMessage.textContent = message;
|
|
1723
|
+
this.elementos.feedbackMessage.className = `sistema-feedback-message ${type} show`;
|
|
1724
|
+
|
|
1725
|
+
setTimeout(() => {
|
|
1726
|
+
this.elementos.feedbackMessage.classList.remove('show');
|
|
1727
|
+
}, 4000);
|
|
1728
|
+
},
|
|
1729
|
+
|
|
1730
|
+
// Obter CSRF token
|
|
1731
|
+
getCsrfToken() {
|
|
1732
|
+
const csrfInput = document.querySelector('[name=csrfmiddlewaretoken]');
|
|
1733
|
+
if (csrfInput) {
|
|
1734
|
+
return csrfInput.value;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
// Fallback do cookie
|
|
1738
|
+
const cookies = document.cookie.split(';');
|
|
1739
|
+
for (let cookie of cookies) {
|
|
1740
|
+
const [name, value] = cookie.trim().split('=');
|
|
1741
|
+
if (name === 'csrftoken') {
|
|
1742
|
+
return value;
|
|
1743
|
+
}
|
|
1711
1744
|
}
|
|
1745
|
+
|
|
1746
|
+
console.warn('⚠️ CSRF token não encontrado');
|
|
1747
|
+
return '';
|
|
1712
1748
|
}
|
|
1713
|
-
|
|
1714
|
-
console.warn('⚠️ CSRF token não encontrado');
|
|
1715
|
-
return '';
|
|
1716
|
-
}
|
|
1717
|
-
};
|
|
1749
|
+
};
|
|
1718
1750
|
|
|
1719
|
-
// Inicialização
|
|
1720
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
});
|
|
1751
|
+
// Inicialização
|
|
1752
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
1753
|
+
console.log('📄 DOM carregado, inicializando sistema...');
|
|
1754
|
+
SistemaVotacao.init();
|
|
1755
|
+
});
|
|
1724
1756
|
|
|
1725
|
-
// Expor globalmente
|
|
1726
|
-
window.SistemaVotacao = SistemaVotacao;
|
|
1757
|
+
// Expor globalmente
|
|
1758
|
+
window.SistemaVotacao = SistemaVotacao;
|
|
1727
1759
|
</script>
|
|
1728
1760
|
{% endblock %}
|