feat: implement finish dialog with unanswered question detection and submit functionality
This commit is contained in:
@@ -563,6 +563,71 @@ img {
|
|||||||
text-align: center;
|
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 {
|
.dialog {
|
||||||
/*display: inline-block;*/
|
/*display: inline-block;*/
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
+17
-8
@@ -31,7 +31,7 @@
|
|||||||
id="btn-submit-nav"
|
id="btn-submit-nav"
|
||||||
class="submit-button navigation nav-right"
|
class="submit-button navigation nav-right"
|
||||||
>
|
>
|
||||||
<b>SUBMIT</b>
|
<b>FINISH</b>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
id="btn-review-overlay"
|
id="btn-review-overlay"
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
class="navigation nav-right"
|
class="navigation nav-right"
|
||||||
title="click to toggle fullscreen"
|
title="click to toggle fullscreen"
|
||||||
>
|
>
|
||||||
fullscreen
|
FULLSCREEN
|
||||||
</button>
|
</button>
|
||||||
<div class="app-name nav-left">RTS</div>
|
<div class="app-name nav-left">RTS</div>
|
||||||
<div id="sync-status" class="nav-left"></div>
|
<div id="sync-status" class="nav-left"></div>
|
||||||
@@ -108,12 +108,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="logout-background">
|
<div class="logout-background" role="dialog" aria-modal="true" aria-labelledby="finish-title">
|
||||||
<div class="logout-panel">
|
<div class="finish-header">
|
||||||
<div class="logout-title">Ready to logout?</div>
|
<div class="login-risr-box"><img class="login-risr-logo" draggable="false" alt="Logo" src="risr-assess-on-dark.png"></div>
|
||||||
<div class="logout-text"></div>
|
</div>
|
||||||
<button class="navigation logout-cancel">continue exam</button>
|
<div class="logout-panel finish-dialog" id="finish-dialog-panel">
|
||||||
<button class="navigation logout-okay">logout now</button>
|
<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>
|
</div>
|
||||||
<div id="options-panel" class="fullscreen-overlay">
|
<div id="options-panel" class="fullscreen-overlay">
|
||||||
|
|||||||
+45
-1
@@ -2031,7 +2031,51 @@ $("#btn-local-file-load").click(function(evt) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(".submit-button").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) {
|
$("#btn-review").click(function(evt) {
|
||||||
|
|||||||
Reference in New Issue
Block a user