feat(lms): replace is_closed with timer limit and auto-submit logic

This commit is contained in:
Dmitry Belan
2026-09-20 17:58:23 +03:00
parent 4b1ea99a4d
commit b3e9d9ae18
5 changed files with 142 additions and 25 deletions
@@ -94,13 +94,87 @@
</div>
{% endfor %}
</div>
{% elif needs_start %}
<div class="mb-6 p-8 text-center rounded-2xl border bg-indigo-50 border-indigo-200">
<span class="material-icons text-indigo-500 text-6xl mb-4">hourglass_top</span>
<h4 class="text-2xl font-bold mb-2 text-indigo-900">Задание на время</h4>
<p class="text-indigo-800 text-lg mb-6">На выполнение этого задания отводится <strong>{{ assignment.time_limit }} минут(ы)</strong>. Как только вы нажмете кнопку ниже, запустится обратный отсчет. По истечении времени ваши ответы будут отправлены автоматически.</p>
<form method="post">
{% csrf_token %}
<input type="hidden" name="action" value="start">
<button type="submit" class="px-8 py-4 bg-indigo-600 text-white text-lg font-bold rounded-xl shadow hover:bg-indigo-700 transition">
Начать выполнение
</button>
</form>
</div>
{% elif not can_submit %}
<div class="mb-6 p-4 rounded-lg border bg-red-50 text-red-800 border-red-200">
<h4 class="font-bold mb-2">Прием ответов завершен</h4>
<p>Вы больше не можете отправлять ответы, так как дедлайн истек или преподаватель закрыл задание.</p>
<p>Вы больше не можете отправлять ответы, так как дедлайн истек или время на выполнение закончилось.</p>
</div>
{% else %}
<form method="post" enctype="multipart/form-data" class="space-y-6">
{% if time_left_seconds is not None %}
<div id="timer-banner" class="sticky top-4 z-50 mb-6 p-4 rounded-xl border bg-indigo-600 text-white shadow-lg flex justify-between items-center">
<div class="flex items-center gap-2">
<span class="material-icons animate-pulse">timer</span>
<span class="font-medium text-lg">Осталось времени:</span>
</div>
<div class="text-2xl font-mono font-bold tracking-wider" id="countdown-display">
--:--:--
</div>
</div>
<script>
let timeLeft = {{ time_left_seconds }};
const display = document.getElementById('countdown-display');
const form = document.getElementById('assignment-form');
function updateTimer() {
if (timeLeft <= 0) {
display.textContent = '00:00:00';
display.classList.add('text-red-300');
// Auto submit
if (form) {
// Prevent multiple submissions
form.onsubmit = null;
const btn = form.querySelector('button[type="submit"]');
if (btn) btn.disabled = true;
// Append a hidden flag
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'auto_submit';
input.value = '1';
form.appendChild(input);
form.submit();
}
return;
}
const h = Math.floor(timeLeft / 3600);
const m = Math.floor((timeLeft % 3600) / 60);
const s = timeLeft % 60;
display.textContent =
(h > 0 ? (h < 10 ? '0' + h : h) + ':' : '') +
(m < 10 ? '0' + m : m) + ':' +
(s < 10 ? '0' + s : s);
if (timeLeft < 60) {
display.classList.add('text-red-300', 'animate-pulse');
}
timeLeft--;
setTimeout(updateTimer, 1000);
}
if (timeLeft > 0) {
updateTimer();
}
</script>
{% endif %}
<form id="assignment-form" method="post" enctype="multipart/form-data" class="space-y-6">
{% csrf_token %}
{% for q, field_type, field in question_fields %}
+5 -5
View File
@@ -52,15 +52,15 @@
Добавлено: {{ assignment.created_at|date:"d M Y" }}
</span>
{% if assignment.deadline %}
<span class="flex items-center gap-1 {% if assignment.is_closed or assignment.deadline < now %}text-red-500{% else %}text-gray-500{% endif %}">
<span class="flex items-center gap-1 {% if assignment.deadline < now %}text-red-500{% else %}text-gray-500{% endif %}">
<span class="material-icons text-[14px]">timer</span>
Дедлайн: {{ assignment.deadline|date:"d M Y, H:i" }}
</span>
{% endif %}
{% if assignment.is_closed %}
<span class="flex items-center gap-1 text-red-500 font-medium mt-1">
<span class="material-icons text-[14px]">lock</span>
Прием ответов закрыт
{% if assignment.time_limit %}
<span class="flex items-center gap-1 text-indigo-600 font-medium mt-1">
<span class="material-icons text-[14px]">hourglass_empty</span>
Время на решение: {{ assignment.time_limit }} мин.
</span>
{% endif %}
</div>