import { render } from "preact";
import { useMemo, useState } from "preact/hooks";
import "./index.css";
const CARD_VALUES = [
{ label: "J", pts: 2 },
{ label: "Q", pts: 3 },
{ label: "K", pts: 4 },
{ label: "3", pts: 10 },
{ label: "A", pts: 11 },
];
function TeamScore({
id,
score,
total,
counts,
opponentCounts,
onAdd,
reverse,
}) {
return (
<div className="flex flex-1 flex-col justify-between p-2">
<div
className={`${reverse ? "order-1" : "order-2"} flex items-start justify-between`}
>
<span className="border border-current px-1 font-bold">
T{id}
</span>
<span className="font-black text-5xl">{score}</span>
<div className="text-right">
<div className="text-xs opacity-50">TOTAL</div>
<div className="font-bold text-lg">{total}</div>
</div>
</div>
<div
className={`${reverse ? "order-2" : "order-1"} grid grid-cols-5 gap-1`}
>
{CARD_VALUES.map((v, i) => (
<button
key={i}
onClick={() => onAdd(id, i, v.pts)}
disabled={counts[i] + opponentCounts[i] >= 4}
className="border border-current p-2 disabled:opacity-20 hover:bg-zinc-100 active:bg-black active:text-white transition-colors"
>
{v.label}
<br />
<span className="text-[9px] opacity-60">
L:{4 - (counts[i] + opponentCounts[i])}
</span>
</button>
))}
</div>
</div>
);
}
function ScorerView({
s1,
s2,
total1,
total2,
c1,
c2,
onAdd,
onClear,
onSave,
}) {
return (
<div className="flex h-full flex-col">
<TeamScore
id={1}
score={s1}
total={total1}
counts={c1}
opponentCounts={c2}
onAdd={onAdd}
reverse
/>
<div className="flex gap-1 border-y border-current bg-zinc-50 p-1 dark:bg-zinc-900">
<button
onClick={onClear}
className="flex-1 border border-current px-2 py-3"
>
CLR
</button>
<button
onClick={onSave}
className="flex-3 border border-current bg-black px-4 py-3 font-black text-white italic dark:bg-zinc-100 dark:text-black"
>
SAVE ROUND
</button>
</div>
<TeamScore
id={2}
score={s2}
total={total2}
counts={c2}
opponentCounts={c1}
onAdd={onAdd}
/>
</div>
);
}
function HistoryView({ history, onPurge }) {
return (
<div className="flex h-full flex-col">
<div className="flex-1 overflow-y-auto">
<table className="w-full border-collapse">
<thead className="sticky top-0 bg-zinc-100 dark:bg-zinc-900">
<tr className="border-current border-b">
<th className="w-10 border-current border-r p-2 text-left">
#
</th>
<th className="border-current border-r p-2 text-center">
T1
</th>
<th className="border-current border-r p-2 text-center">
T2
</th>
<th className="p-2 text-right">CUMUL</th>
</tr>
</thead>
<tbody>
{history.map((r, i) => {
const h1 = history
.slice(0, i + 1)
.reduce((a, b) => a + b.t1, 0);
const h2 = history
.slice(0, i + 1)
.reduce((a, b) => a + b.t2, 0);
return (
<tr key={i} className="border-current border-b">
<td className="border-current border-r p-2 opacity-50">
{i + 1}
</td>
<td className="border-current border-r p-2 text-center font-bold">
{r.t1}
</td>
<td className="border-current border-r p-2 text-center font-bold">
{r.t2}
</td>
<td className="p-2 text-right italic opacity-70">
{h1} / {h2}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
<button
onClick={onPurge}
className="w-full border-current border-t p-4 font-bold text-red-600 dark:text-red-400"
>
PURGE HISTORY
</button>
</div>
);
}
export function App() {
const [tab, setTab] = useState("score");
const [s1, setS1] = useState(0);
const [s2, setS2] = useState(0);
const [c1, setC1] = useState([0, 0, 0, 0, 0]);
const [c2, setC2] = useState([0, 0, 0, 0, 0]);
const [history, setHistory] = useState([]);
const histT1 = useMemo(
() => history.reduce((a, b) => a + b.t1, 0),
[history],
);
const histT2 = useMemo(
() => history.reduce((a, b) => a + b.t2, 0),
[history],
);
const add = (team, idx, pts) => {
if (c1[idx] + c2[idx] >= 4) return;
if (team === 1) {
setS1((v) => v + pts);
setC1((v) => {
const n = [...v];
n[idx]++;
return n;
});
} else {
setS2((v) => v + pts);
setC2((v) => {
const n = [...v];
n[idx]++;
return n;
});
}
};
const clearRound = () => {
setS1(0);
setS2(0);
setC1([0, 0, 0, 0, 0]);
setC2([0, 0, 0, 0, 0]);
};
const save = () => {
if (s1 === 0 && s2 === 0) return;
setHistory((prev) => [...prev, { t1: s1, t2: s2 }]);
clearRound();
};
return (
<div className="flex h-screen flex-col bg-white font-mono text-black text-xs uppercase dark:bg-zinc-950 dark:text-zinc-100">
<div className="flex border-current border-b">
<button
onClick={() => setTab("score")}
className={`flex-1 border-r border-current p-3 font-bold ${tab === "score" ? "bg-black text-white dark:bg-white dark:text-black" : ""}`}
>
[0] SCORER
</button>
<button
onClick={() => setTab("hist")}
className={`flex-1 p-3 font-bold ${tab === "hist" ? "bg-black text-white dark:bg-white dark:text-black" : ""}`}
>
[1] HISTORY ({history.length})
</button>
</div>
<div className="flex-1 overflow-auto">
{tab === "score" ? (
<ScorerView
s1={s1}
s2={s2}
total1={histT1 + s1}
total2={histT2 + s2}
c1={c1}
c2={c2}
onAdd={add}
onClear={clearRound}
onSave={save}
/>
) : (
<HistoryView
history={history}
onPurge={() => confirm("purge?") && setHistory([])}
/>
)}
</div>
</div>
);
}
render(<App />, document.getElementById("app"));