cs-bingo/src/App.tsx
2024-03-29 01:07:23 +01:00

116 lines
3.7 KiB
TypeScript

import React, { Fragment, useEffect, useState } from 'react';
import './App.css';
import {prompts} from './prompts';
const alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ";
const lskey_prompts = "cs_bingo_prompts-day2";
const lskey_ticked = "cs_bingo_ticked-day2";
const shuffle = <T,>(array: T[]): T[] => {
return array
.map((item) => ({ key: Math.random(), value: item }))
.sort((a, b) => b.key - a.key)
.map((item) => item.value);
}
const App: React.FC<{}> = () => {
const [resetCounter, setResetCounter] = useState(0);
const [lines, setLines] = useState<[string,string][]>([]);
const saveLines = (lines: [string,string][]) => {
localStorage.setItem(lskey_prompts, JSON.stringify(lines));
};
const saveTicks = (lines: boolean[]) => {
localStorage.setItem(lskey_ticked, JSON.stringify(lines));
};
const [highlighted, setHighlighted] = useState<null| number>(null);
const highlight = (index: number) => {
setHighlighted(index);
setTimeout(() => setHighlighted(null), 3000);
document.getElementById("letter-" + alphabet[index])?.scrollIntoView();
};
useEffect(() => {
console.log("no lines");
if (lines.length !== 0) return;
const loadLines = localStorage.getItem(lskey_prompts);
const loadTicks = localStorage.getItem(lskey_ticked);
if (loadLines === null || loadTicks === null) {
const newPrompts = shuffle(prompts).slice(0, 25)
const newTicks = new Array(25).fill(false);
setLines(newPrompts);
setTicked(newTicks);
saveLines(newPrompts);
saveTicks(newTicks);
} else {
setLines(JSON.parse(loadLines));
setTicked(JSON.parse(loadTicks));
}
}, [lines])
const [ticked, setTicked] = useState<boolean[]>(new Array(25).fill(false) );
const toggleField = (index: number) => {
console.log("ticking", index);
setTicked((old) => {
const newTicks = old.map((e, i) => i === index ? !e : e);
saveTicks(newTicks);
return newTicks;
});
};
const incCounter = () => {
setResetCounter((old) => {
if (old === 15) {
const newPrompts = shuffle(prompts).slice(0, 25)
const newTicked = new Array(25).fill(false) ;
setLines(newPrompts);
setTicked(newTicked);
saveLines(newPrompts);
saveTicks(newTicked)
}
return old + 1;
});
}
return (
<div className="container">
<h1 className="title" onClick={incCounter}>CS Bingo</h1>
<div className="bingo-board">
{Array.from(alphabet).map((e, index) =>
<div key={index} >
<div className={ticked[index] ? "begone": undefined} onClick={() => {
// fuck IOS not sending onContextMenu events
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
toggleField(index);
} else {
highlight(index);
}
}} onContextMenu={(e) => {e.preventDefault(); toggleField(index);}}>
<span>{e}</span>
</div>
</div>
)}
</div>
<hr/>
<div className="legend">
<div className="header">
<span>Letter</span>
</div>
<div className="header">
<span>Goal</span>
</div>
{lines.map(([category, line], index)=>
<Fragment key={index}>
<div className="entry-letter" id={"letter-" + alphabet[index]}>
<span>{alphabet[index]}</span>
</div>
<div className={"entry-text" + (highlighted === index ? " highlighted" : "")} >
<span>{line}</span>
</div>
</Fragment>
)}
</div>
</div>
);
}
export default App;