diff --git a/frontend/src/features/jobs/PostJobPage.jsx b/frontend/src/features/jobs/PostJobPage.jsx
index 9acfd9f..c337eec 100644
--- a/frontend/src/features/jobs/PostJobPage.jsx
+++ b/frontend/src/features/jobs/PostJobPage.jsx
@@ -26,6 +26,9 @@ export default function PostJobPage({ onUnauthorized, onCancel, onViewJobs }) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [expired, setExpired] = useState(() => new Set());
+ // Index of the question currently on screen. Only this one is mounted, so only
+ // its countdown runs; advancing remounts the next card with a fresh clock.
+ const [currentIndex, setCurrentIndex] = useState(0);
// Live countdown per question, kept in a ref so ticking never re-renders the page.
const timeLeft = useRef({});
@@ -35,11 +38,31 @@ export default function PostJobPage({ onUnauthorized, onCancel, onViewJobs }) {
const sent = useRef({ answers: false, followup: false });
const limit = quiz?.time_limit_seconds ?? 75;
+ const questions = quiz?.questions ?? [];
+ const currentQuestion = questions[currentIndex] ?? null;
+ const isLastQuestion = currentIndex >= questions.length - 1;
function markExpired(id) {
setExpired((prev) => (prev.has(id) ? prev : new Set(prev).add(id)));
}
+ // Moving on forfeits whatever time is left on the current question; the clock is
+ // per question, so there is no going back to spend it later.
+ function advance() {
+ if (isLastQuestion) {
+ handleSubmit();
+ } else {
+ setCurrentIndex(currentIndex + 1);
+ }
+ }
+
+ // Expiry locks the answer as-is and moves straight on, so the poster never sits
+ // on a dead card. Running out on the last question commits the round.
+ function handleExpire(id) {
+ markExpired(id);
+ advance();
+ }
+
function reset() {
setQuiz(null);
setAnswers({});
@@ -48,6 +71,7 @@ export default function PostJobPage({ onUnauthorized, onCancel, onViewJobs }) {
setResult(null);
setError("");
setExpired(new Set());
+ setCurrentIndex(0);
timeLeft.current = {};
inputSignal.current = {};
sent.current = { answers: false, followup: false };
@@ -122,13 +146,6 @@ export default function PostJobPage({ onUnauthorized, onCancel, onViewJobs }) {
}
}
- // When every question's clock has run out, submit whatever is there.
- useEffect(() => {
- if (quiz && !followup && !result && expired.size >= quiz.questions.length) {
- handleSubmit();
- }
- }, [expired, quiz, followup, result]);
-
const followupExpired = followup && expired.has(followup.followup.id);
useEffect(() => {
if (followupExpired && !result) handleFollowUp();
@@ -180,18 +197,20 @@ export default function PostJobPage({ onUnauthorized, onCancel, onViewJobs }) {