Style reading quiz feedback by result
This commit is contained in:
1 parent
f607994a5d
commit
77553bbece
3 files changed
+38
-9
No files matched your search
+5
-1
@@ -395,7 +395,11 @@ body.reader { position: fixed; top: 0; left: 0; right: 0; bottom: 0; overflow: h
|
|||||||
.reading-gate-question { margin: 20px 0; }
|
.reading-gate-question { margin: 20px 0; }
|
||||||
.reading-gate-question input { display: block; box-sizing: border-box; width: 100%; margin: 14px 0; padding: 10px; }
|
.reading-gate-question input { display: block; box-sizing: border-box; width: 100%; margin: 14px 0; padding: 10px; }
|
||||||
.reading-gate-actions { display: flex; flex-wrap: wrap; gap: 10px; }
|
.reading-gate-actions { display: flex; flex-wrap: wrap; gap: 10px; }
|
||||||
.reading-gate-message { color: var(--accent); min-height: 1.5em; }
|
.reading-gate-message { margin: 18px 0 0; padding: 11px 13px; border: 1px solid #46505b;
|
||||||
|
border-radius: 9px; background: #222a33; color: #d8e6f4; }
|
||||||
|
.reading-gate-message[data-tone="success"] { border-color: #39765a; background: #193528; color: #b8f2d0; }
|
||||||
|
.reading-gate-message[data-tone="retry"] { border-color: #9b7233; background: #382b1a; color: #ffdaa0; }
|
||||||
|
.reading-gate-message[data-tone="error"] { border-color: #944c55; background: #3c2025; color: #ffc0c6; }
|
||||||
@media (max-width: 660px) { .reading-gate { margin: 28px 12px 100px; padding: 18px; } }
|
@media (max-width: 660px) { .reading-gate { margin: 28px 12px 100px; padding: 18px; } }
|
||||||
.pg { position: absolute; overflow: hidden; background: #19191c; }
|
.pg { position: absolute; overflow: hidden; background: #19191c; }
|
||||||
.pg img { display: block; width: 100%; height: 100%; -webkit-user-drag: none; }
|
.pg img { display: block; width: 100%; height: 100%; -webkit-user-drag: none; }
|
||||||
|
|||||||
+13
-8
@@ -22,7 +22,12 @@
|
|||||||
h('h1', {}, 'Reading is closed right now'),
|
h('h1', {}, 'Reading is closed right now'),
|
||||||
h('p', {}, `The reading hours are set by this server's deployment (${access.timezone}). The library and your progress remain available.`),
|
h('p', {}, `The reading hours are set by this server's deployment (${access.timezone}). The library and your progress remain available.`),
|
||||||
h('p', {}, `Answer five questions drawn from manga you have already read to unlock ${access.unlockMinutes} minutes of reading. There is no answer timer or retry limit.`));
|
h('p', {}, `Answer five questions drawn from manga you have already read to unlock ${access.unlockMinutes} minutes of reading. There is no answer timer or retry limit.`));
|
||||||
const message = h('p', { class: 'reading-gate-message', role: 'status' });
|
const message = h('p', { class: 'reading-gate-message', role: 'status', hidden: true });
|
||||||
|
const setMessage = (text, tone = 'info') => {
|
||||||
|
message.textContent = text;
|
||||||
|
message.dataset.tone = tone;
|
||||||
|
message.hidden = !text;
|
||||||
|
};
|
||||||
const question = h('div', { class: 'reading-gate-question' });
|
const question = h('div', { class: 'reading-gate-question' });
|
||||||
const start = h('button', { class: 'btn', type: 'button' }, 'Start five-question challenge');
|
const start = h('button', { class: 'btn', type: 'button' }, 'Start five-question challenge');
|
||||||
const back = h('a', { class: 'btn', href: mangaUrl(P.get('m')) }, 'Back to manga');
|
const back = h('a', { class: 'btn', href: mangaUrl(P.get('m')) }, 'Back to manga');
|
||||||
@@ -39,22 +44,22 @@
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
try {
|
try {
|
||||||
const result = await api('api/reading-quiz/answer', { m: P.get('m'), challenge, answer: input.value });
|
const result = await api('api/reading-quiz/answer', { m: P.get('m'), challenge, answer: input.value });
|
||||||
if (!result.correct) { message.textContent = 'Not quite. Try another spelling or answer—there is no attempt limit.'; input.select(); return; }
|
if (!result.correct) { setMessage('Not quite. Try another spelling or answer—there is no attempt limit.', 'retry'); input.select(); return; }
|
||||||
if (result.complete) { message.textContent = 'Unlocked. Opening your chapter…'; location.reload(); return; }
|
if (result.complete) { setMessage('Unlocked. Opening your chapter…', 'success'); location.reload(); return; }
|
||||||
message.textContent = 'Correct.';
|
setMessage('Correct.', 'success');
|
||||||
showQuestion(result);
|
showQuestion(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
message.textContent = error.message;
|
setMessage(error.message, 'error');
|
||||||
if (/challenge expired/i.test(error.message)) { challenge = null; question.textContent = ''; start.hidden = false; }
|
if (/challenge expired/i.test(error.message)) { challenge = null; question.textContent = ''; start.hidden = false; }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
question.append(form); input.focus();
|
question.append(form); input.focus();
|
||||||
};
|
};
|
||||||
start.addEventListener('click', async () => {
|
start.addEventListener('click', async () => {
|
||||||
try { showQuestion(await api('api/reading-quiz/start', { m: P.get('m') })); start.hidden = true; message.textContent = ''; }
|
try { showQuestion(await api('api/reading-quiz/start', { m: P.get('m') })); start.hidden = true; setMessage(''); }
|
||||||
catch (error) { message.textContent = error.message; }
|
catch (error) { setMessage(error.message, 'error'); }
|
||||||
});
|
});
|
||||||
if (!access.quizAvailable) { start.hidden = true; message.textContent = 'Fewer than five questions match your completed chapters. Please return during reading hours.'; }
|
if (!access.quizAvailable) { start.hidden = true; setMessage('Fewer than five questions match your completed chapters. Please return during reading hours.', 'info'); }
|
||||||
window.addEventListener('pagehide', () => {
|
window.addEventListener('pagehide', () => {
|
||||||
if (challenge) navigator.sendBeacon('api/reading-quiz/abandon', new Blob([JSON.stringify({ challenge })], { type: 'application/json' }));
|
if (challenge) navigator.sendBeacon('api/reading-quiz/abandon', new Blob([JSON.stringify({ challenge })], { type: 'application/json' }));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -109,6 +109,26 @@ let keep = false;
|
|||||||
await page.getByRole('heading', { name: 'Reading is closed right now' }).waitFor();
|
await page.getByRole('heading', { name: 'Reading is closed right now' }).waitFor();
|
||||||
await page.getByRole('button', { name: 'Start five-question challenge' }).click();
|
await page.getByRole('button', { name: 'Start five-question challenge' }).click();
|
||||||
await page.getByText('Question 1 of 5').waitFor();
|
await page.getByText('Question 1 of 5').waitFor();
|
||||||
|
const firstPrompt = await page.locator('.reading-gate-question h2').textContent();
|
||||||
|
const firstTitle = await page.locator('.reading-gate-question .muted').textContent();
|
||||||
|
const firstNumber = /question (\d)/.exec(firstPrompt)[1];
|
||||||
|
const answerBox = page.getByRole('textbox', { name: 'Your answer' });
|
||||||
|
await answerBox.fill('wrong');
|
||||||
|
await page.getByRole('button', { name: 'Check answer' }).click();
|
||||||
|
const retryNotice = page.locator('.reading-gate-message[data-tone="retry"]');
|
||||||
|
await retryNotice.waitFor();
|
||||||
|
const retryStyle = await retryNotice.evaluate(el => ({ color: getComputedStyle(el).color,
|
||||||
|
border: getComputedStyle(el).borderTopWidth, background: getComputedStyle(el).backgroundColor }));
|
||||||
|
assert.notEqual(retryStyle.border, '0px');
|
||||||
|
await answerBox.fill((firstTitle === 'Moon Garden' ? 'moonanswer' : 'rainanswer') + firstNumber);
|
||||||
|
await page.getByRole('button', { name: 'Check answer' }).click();
|
||||||
|
const successNotice = page.locator('.reading-gate-message[data-tone="success"]');
|
||||||
|
await successNotice.waitFor();
|
||||||
|
const successStyle = await successNotice.evaluate(el => ({ color: getComputedStyle(el).color,
|
||||||
|
background: getComputedStyle(el).backgroundColor }));
|
||||||
|
assert.notEqual(successStyle.color, retryStyle.color);
|
||||||
|
assert.notEqual(successStyle.background, retryStyle.background);
|
||||||
|
await page.getByText('Question 2 of 5').waitFor();
|
||||||
await page.goto(url + '/manga.html?m=' + encodeURIComponent(manga));
|
await page.goto(url + '/manga.html?m=' + encodeURIComponent(manga));
|
||||||
await page.goto(url + '/read.html?m=' + encodeURIComponent(manga) + '&c=' + encodeURIComponent(chapter));
|
await page.goto(url + '/read.html?m=' + encodeURIComponent(manga) + '&c=' + encodeURIComponent(chapter));
|
||||||
await page.getByRole('button', { name: 'Start five-question challenge' }).waitFor();
|
await page.getByRole('button', { name: 'Start five-question challenge' }).waitFor();
|
||||||
|
|||||||
Reference in new issue
Block a user