feat: implement finish dialog with unanswered question detection and submit functionality

This commit is contained in:
Ross
2026-06-29 12:37:20 +01:00
parent 873d05e7cd
commit f74aba0e9c
3 changed files with 127 additions and 9 deletions
+65
View File
@@ -563,6 +563,71 @@ img {
text-align: center;
}
/* Finish dialog styling */
.finish-header {
display: flex;
justify-content: center;
padding-top: 6vh;
pointer-events: none;
}
.login-risr-box {
display: inline-block;
}
.login-risr-logo {
height: 64px;
width: auto;
user-drag: none;
}
.finish-dialog {
display: inline-block;
background-color: #1b1b1b;
color: #fff;
margin: 3vh auto;
padding: 1.6rem;
border-radius: 8px;
max-width: 520px;
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
text-align: left;
}
.logout-title {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 0.8rem;
}
.logout-error.info {
background-color: #e3f2fd;
color: #0d47a1;
border: 1px solid rgba(13,71,161,0.15);
padding: 0.8rem;
border-radius: 4px;
margin-bottom: 0.8rem;
}
.logout-text {
margin-bottom: 0.8rem;
color: #ddd;
}
.logout-buttons {
display: flex;
gap: 0.6rem;
justify-content: flex-end;
}
.logout-button {
padding: 0.6rem 1rem;
border-radius: 4px;
border: none;
cursor: pointer;
font-weight: 600;
}
.logout-button.danger {
background: #b71c1c;
color: white;
}
.logout-button.primary {
background: #1976d2;
color: white;
}
.dialog {
/*display: inline-block;*/
display: none;
+17 -8
View File
@@ -31,7 +31,7 @@
id="btn-submit-nav"
class="submit-button navigation nav-right"
>
<b>SUBMIT</b>
<b>FINISH</b>
</button>
<button
id="btn-review-overlay"
@@ -45,7 +45,7 @@
class="navigation nav-right"
title="click to toggle fullscreen"
>
fullscreen
FULLSCREEN
</button>
<div class="app-name nav-left">RTS</div>
<div id="sync-status" class="nav-left"></div>
@@ -108,12 +108,21 @@
</div>
</div>
</div>
<div class="logout-background">
<div class="logout-panel">
<div class="logout-title">Ready to logout?</div>
<div class="logout-text"></div>
<button class="navigation logout-cancel">continue exam</button>
<button class="navigation logout-okay">logout now</button>
<div class="logout-background" role="dialog" aria-modal="true" aria-labelledby="finish-title">
<div class="finish-header">
<div class="login-risr-box"><img class="login-risr-logo" draggable="false" alt="Logo" src="risr-assess-on-dark.png"></div>
</div>
<div class="logout-panel finish-dialog" id="finish-dialog-panel">
<div class="logout-title" id="finish-title">Ready to finish?</div>
<div class="logout-error info">
<p><strong>Answers are submitted automatically. You can complete the exam by clicking below.</strong></p>
<p class="unanswered-line">You have <span id="unanswered-count">0</span> unanswered questions</p>
</div>
<div class="logout-text">Click “Submit exam” before closing the tab or window</div>
<div class="logout-buttons">
<button class="logout-button danger" id="button-logout">Submit exam</button>
<button class="logout-button primary" id="button-continue">Continue exam</button>
</div>
</div>
</div>
<div id="options-panel" class="fullscreen-overlay">
+45 -1
View File
@@ -2031,7 +2031,51 @@ $("#btn-local-file-load").click(function(evt) {
});
$(".submit-button").click(function(evt) {
interact.submitAnswers(exam_details, db, URLS);
// Show a finish dialog similar to the app style
// Compute unanswered count from the answers DB and show the dialog
interact
.getJsonAnswers(exam_details, db)
.then((answers) => {
// Count unique question ids answered
const qids = new Set();
answers.forEach((a) => {
if (a && a.qid) qids.add(a.qid.toString());
});
const totalQuestions =
exam_details.number_of_questions || (exam_details.question_order && exam_details.question_order.length) || 0;
const answeredCount = qids.size;
const unanswered = Math.max(0, totalQuestions - answeredCount);
$("#unanswered-count").text(unanswered);
// Update messaging for clarity
if (unanswered === 0) {
$(".logout-error.info p.unanswered-line").text("All questions have answers.");
} else if (totalQuestions === 0) {
$(".logout-error.info p.unanswered-line").text(`You have ${unanswered} unanswered question(s)`);
} else {
$(".logout-error.info p.unanswered-line").text(`You have ${unanswered} unanswered question(s)`);
}
// Show dialog overlay
$(".logout-background").fadeIn(150);
// Wire dialog buttons
$("#button-logout").off("click").on("click", function() {
interact.submitAnswers(exam_details, db, URLS);
$(".logout-background").fadeOut(150);
});
$("#button-continue").off("click").on("click", function() {
$(".logout-background").fadeOut(150);
});
})
.catch((e) => {
console.debug("Error computing unanswered count", e);
$("#unanswered-count").text("?");
$(".logout-background").fadeIn(150);
});
});
$("#btn-review").click(function(evt) {