fix layout a bit and add auto-advance timer
This commit is contained in:
@@ -53,6 +53,7 @@ export class Game {
|
||||
private sampler: Sampler;
|
||||
private state: GameState;
|
||||
private onUpdate: () => void;
|
||||
private autoAdvanceTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
constructor(onUpdate: () => void) {
|
||||
this.onUpdate = onUpdate;
|
||||
@@ -138,6 +139,12 @@ export class Game {
|
||||
}
|
||||
|
||||
nextQuestion(): void {
|
||||
// Clear any pending auto-advance timeout
|
||||
if (this.autoAdvanceTimeout) {
|
||||
clearTimeout(this.autoAdvanceTimeout);
|
||||
this.autoAdvanceTimeout = null;
|
||||
}
|
||||
|
||||
this.state.currentQuestion = this.sampler.generateQuestion();
|
||||
this.state.selectedAnswer = null;
|
||||
this.state.selectedIndex = -1;
|
||||
@@ -168,6 +175,13 @@ export class Game {
|
||||
this.state.isCorrect
|
||||
);
|
||||
|
||||
// Auto-advance after 1 second for correct answers
|
||||
if (this.state.isCorrect) {
|
||||
this.autoAdvanceTimeout = setTimeout(() => {
|
||||
this.nextQuestion();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
this.save();
|
||||
this.onUpdate();
|
||||
}
|
||||
|
||||
20
src/main.ts
20
src/main.ts
@@ -35,23 +35,16 @@ function render(): void {
|
||||
? renderTypeBadge(q.defenderTypes[0], 'large')
|
||||
: `${renderTypeBadge(q.defenderTypes[0], 'large')} / ${renderTypeBadge(q.defenderTypes[1], 'large')}`;
|
||||
|
||||
const optionsHtml = options.map((opt, i) => {
|
||||
const optionsHtml = state.showResult ? '' : options.map((opt, i) => {
|
||||
let cls = 'option-btn';
|
||||
if (state.showResult) {
|
||||
if (opt.value === q.correctAnswer) {
|
||||
cls += ' correct';
|
||||
} else if (i === state.selectedIndex && !state.isCorrect) {
|
||||
cls += ' wrong';
|
||||
}
|
||||
} else if (i === state.selectedIndex) {
|
||||
if (i === state.selectedIndex) {
|
||||
cls += ' selected';
|
||||
}
|
||||
|
||||
const shortcut = `${startKey + i}`;
|
||||
const disabled = state.showResult ? 'disabled' : '';
|
||||
|
||||
return `
|
||||
<button class="${cls}" data-index="${i}" ${disabled}>
|
||||
<button class="${cls}" data-index="${i}">
|
||||
<span class="option-key">${shortcut}</span>
|
||||
<span class="option-label">${opt.label}</span>
|
||||
</button>
|
||||
@@ -65,7 +58,7 @@ function render(): void {
|
||||
: `<div class="result-title">✗ Wrong</div>
|
||||
<div class="explanation">${game.getExplanation()}</div>`
|
||||
}
|
||||
<button class="next-btn">Next Question (Enter)</button>
|
||||
${!state.isCorrect ? '<button class="next-btn">Continue (Enter)</button>' : ''}
|
||||
</div>
|
||||
` : '';
|
||||
|
||||
@@ -100,12 +93,11 @@ function render(): void {
|
||||
|
||||
<div class="options">
|
||||
${optionsHtml}
|
||||
${resultHtml}
|
||||
</div>
|
||||
|
||||
${resultHtml}
|
||||
|
||||
<footer class="footer">
|
||||
<span class="hint">Press ${startKey}-${startKey + options.length - 1} to select • Enter to continue</span>
|
||||
<span class="hint">${state.showResult && !state.isCorrect ? 'Press Enter to continue' : `Press ${startKey}-${startKey + options.length - 1} to select`}</span>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -163,6 +163,23 @@ body {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Result shown in place of options */
|
||||
.options .result {
|
||||
padding: 24px 20px;
|
||||
border-radius: var(--border-radius);
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
.result.correct {
|
||||
background: rgba(74, 222, 128, 0.1);
|
||||
border: 1px solid rgba(74, 222, 128, 0.3);
|
||||
}
|
||||
|
||||
.result.wrong {
|
||||
background: rgba(248, 113, 113, 0.1);
|
||||
border: 1px solid rgba(248, 113, 113, 0.3);
|
||||
}
|
||||
|
||||
.option-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -544,7 +561,7 @@ body {
|
||||
|
||||
/* Full Type Chart */
|
||||
.full-chart-section {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chart-toggle-row {
|
||||
@@ -577,9 +594,18 @@ body {
|
||||
|
||||
.full-type-chart {
|
||||
display: grid;
|
||||
grid-template-columns: 50px repeat(18, 1fr);
|
||||
gap: 2px;
|
||||
font-size: 0.65rem;
|
||||
grid-template-columns: repeat(19, 1fr);
|
||||
gap: 1px;
|
||||
font-size: min(0.55rem, 1.8vw);
|
||||
width: 100%;
|
||||
max-width: 100vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chart-toggle.active {
|
||||
background: var(--accent);
|
||||
border-color: var(--accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.full-chart-header-row {
|
||||
@@ -587,8 +613,7 @@ body {
|
||||
}
|
||||
|
||||
.full-chart-corner {
|
||||
width: 50px;
|
||||
height: 40px;
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -597,12 +622,10 @@ body {
|
||||
}
|
||||
|
||||
.full-chart-header {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.55rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
border-radius: 3px;
|
||||
@@ -613,34 +636,31 @@ body {
|
||||
}
|
||||
|
||||
.full-chart-row-header {
|
||||
width: 50px;
|
||||
height: 40px;
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.55rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.full-chart-cell {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.55rem;
|
||||
font-weight: 600;
|
||||
border-radius: 3px;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.full-chart-cell:hover {
|
||||
transform: scale(1.15);
|
||||
transform: scale(1.1);
|
||||
z-index: 1;
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
|
||||
Reference in New Issue
Block a user