Implement balanced row grouping for question navigator without horizontal scroll

This commit is contained in:
2026-04-26 12:30:48 +02:00
parent 1c030c8ed1
commit d665a98c7d
+40 -13
View File
@@ -1175,19 +1175,46 @@ function WettkampfQuizPage({ params, navigate }) {
<div className="h-full rounded-full transition-all" style={{ width: `${(answeredCount / questions.length) * 100}%`, backgroundColor: accentColor }} />
</div>
{/* Question navigator */}
<div className="flex gap-1.5 mb-4 overflow-x-auto pb-2 justify-start sm:justify-center">
{questions.map((question, i) => {
const a = answers[question.id];
const isAnswered = a && a.selected && a.selected.length > 0 && a.selected[0] !== '';
const isCurrent = i === index;
const style = {};
let cls = 'w-9 h-9 flex-shrink-0 rounded-lg text-sm font-bold transition-all ';
if (isCurrent) { cls += 'text-white ring-2'; style.backgroundColor = '#f59e0b'; style.boxShadow = '0 0 0 2px #fcd34d'; }
else if (isAnswered) { cls += 'text-white'; style.backgroundColor = accentColor; }
else cls += 'bg-gray-700 text-gray-400 hover:bg-gray-600';
return <button key={question.id} onClick={() => setIndex(i)} className={cls} style={style}>{i + 1}</button>;
})}
<div className="mb-4">
{(() => {
const N = questions.length;
if (N === 0) return null;
const R = Math.ceil(N / 20);
const chunks = [];
const baseSize = Math.floor(N / R);
let remainder = N % R;
let startIndex = 0;
for (let i = 0; i < R; i++) {
const chunkSize = baseSize + (remainder > 0 ? 1 : 0);
remainder--;
const chunk = [];
for (let j = 0; j < chunkSize; j++) {
chunk.push({ q: questions[startIndex + j], origIndex: startIndex + j });
}
chunks.push(chunk);
startIndex += chunkSize;
}
return (
<div className="flex flex-col gap-1.5 sm:gap-2 items-center w-full">
{chunks.map((chunk, rowIdx) => (
<div key={rowIdx} className="flex gap-1 sm:gap-1.5 justify-center w-full flex-wrap">
{chunk.map(({ q, origIndex }) => {
const a = answers[q.id];
const isAnswered = a && a.selected && a.selected.length > 0 && a.selected[0] !== '';
const isCurrent = origIndex === index;
const style = {};
// w-7 allows for more questions per row on smaller screens
let cls = 'w-7 h-7 sm:w-8 sm:h-8 md:w-9 md:h-9 rounded-md sm:rounded-lg text-xs sm:text-sm font-bold transition-all flex items-center justify-center shrink-0 ';
if (isCurrent) { cls += 'text-white ring-2'; style.backgroundColor = '#f59e0b'; style.boxShadow = '0 0 0 2px #fcd34d'; }
else if (isAnswered) { cls += 'text-white'; style.backgroundColor = accentColor; }
else cls += 'bg-gray-700 text-gray-400 hover:bg-gray-600';
return <button key={q.id} onClick={() => setIndex(origIndex)} className={cls} style={style}>{origIndex + 1}</button>;
})}
</div>
))}
</div>
);
})()}
</div>
{/* Status */}