Skip to content

Instantly share code, notes, and snippets.

@shmshrbali
Created December 13, 2024 04:16
Show Gist options
  • Select an option

  • Save shmshrbali/28889697ff317107d766396a6062ff02 to your computer and use it in GitHub Desktop.

Select an option

Save shmshrbali/28889697ff317107d766396a6062ff02 to your computer and use it in GitHub Desktop.
Kamo's Quiz
<div id="app"></div>
const { useState, useEffect } = React;
const App = () => {
const [players, setPlayers] = useState([
{
name: "SA",
scoring: [0]
},
{
name: "IP",
scoring: [0]
},
{
name: "ME",
scoring: [0]
},
{
name: "BO",
scoring: [0]
}
]);
const changeScore = (pi, si, score) => {
let oldP = players;
oldP[pi].scoring[si] = score;
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
const addScore = (pi, si) => {
let oldP = players;
oldP[pi].scoring[si] = oldP[pi].scoring[si] + 1;
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
const minusScore = (pi, si) => {
let oldP = players;
oldP[pi].scoring[si] = oldP[pi].scoring[si] - 1;
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
const changeName = (pi, name) => {
let oldP = players;
oldP[pi].name = name;
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
const clearRound = () => {
setPlayers([
{
name: "New Player 1",
scoring: [0]
},
{
name: "New Player 2",
scoring: [0]
},
{
name: "New Player 3",
scoring: [0]
},
{
name: "New Player 4",
scoring: [0]
}
]);
localforage.setItem("kq_players", [
{
name: "New Player 1",
scoring: [0]
},
{
name: "New Player 2",
scoring: [0]
},
{
name: "New Player 3",
scoring: [0]
},
{
name: "New Player 4",
scoring: [0]
}
]);
};
const newRound = () => {
let oldP = players;
for (i = 0; i < oldP.length; i++) {
console.log(oldP[i]);
oldP[i].scoring[oldP[i].scoring.length] = 0;
}
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
const addPlayer = () => {
let oldP = players;
oldP[oldP.length] = {
name: "New Player 1",
scoring: [0]
};
setPlayers([...oldP]);
localforage.setItem("kq_players", oldP);
};
useEffect(() => {
localforage.getItem("kq_players", function (err, value) {
setPlayers([...value]);
});
}, []);
return (
<div className="min-h-screen bg-gray-900 flex justify-between items-center w-full flex-col flex-wrap py-8">
<div class="bgimage z-0 opacity-[0.05]"></div>
<div class="w-full relative z-10">
<h1 className="text-3xl text-gray-100 text-center leading-9 tracking-tight mb-8">
Kamo's Quiz of People
</h1>
<div class='w-full max-h-[65vh] overflow-auto'>
<div class="text-white text-center flex w-full gap-4 divide-x-0 divide-gray-800 border-0 border-gray-700 px-8">
{players.map((pl, index) => {
return (
<div class="shrink-0 ring-1 ring-gray-950 bg-gray-900 relative">
<h3 class="px-6 border-b py-4 sticky top-0 bg-gray-950 border-gray-700">
<input
type="text"
value={pl.name}
class="bg-gray-800 text-center rounded-xl px-4 py-1 uppercase text-xs tracking-widest min-w-0 max-w-auto inline"
style={{ fieldSizing: "content" }}
onChange={(e) => changeName(index, e.target.value)}
/>
</h3>
<div class="flex flex-col gap-0 divide-y divide-gray-800 text-center">
{pl.scoring.map((sc, i) => {
return (
<div class="py-3 px-4 text-gray-300 font-extralight text-xs flex flex-col gap-2">
<div class="flex gap-2 items-center justify-center">
{i + 1}:
<input
type="number"
value={sc}
class="bg-transparent border border-gray-800 appearance-none text-center rounded-xl px-2 py-0.5 uppercase text-base tracking-widest w-12"
onChange={(e) =>
changeScore(index, i, parseInt(e.target.value))
}
/>
</div>
{pl.scoring.length - 1 === i && (
<div class="grid grid-cols-2 gap-2">
<button
class="flex items-center justify-center px-2 py-0 rounded-lg bg-gray-950 text-xl font-black"
onClick={() => minusScore(index, i)}
>
-
</button>
<button
class="flex items-center justify-center px-2 py-0 rounded-lg bg-gray-950 text-xl font-black"
onClick={() => addScore(index, i)}
>
+
</button>
</div>
)}
</div>
);
})}
</div>
<div class="py-2 px-8 border-t bg-gray-950 border-gray-700 font-black sticky bottom-0">
{pl.scoring.reduce((partialSum, a) => partialSum + a, 0)}
</div>
</div>
);
})}
</div>
</div>
</div>
<div class="flex mt-4 gap-4 w-full justify-between px-8">
<button
class="p-2 px-4 text-center text-xs font-bold bg-black rounded-xl text-white"
onClick={() => addPlayer()}
>
Add Player
</button>
<div class="flex gap-4 justify-end">
<button
class="p-2 px-4 text-center text-xs font-bold bg-transparent rounded-xl border border-white text-white"
onClick={() => clearRound()}
>
Clear
</button>
<button
class="p-2 px-4 text-center text-xs font-bold bg-green-700 rounded-xl text-white"
onClick={() => newRound()}
>
New Round
</button>
</div>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js"></script>
/* Tailwindeth has been added but ye can remove it and roll yee own CSS */
/* I've had too much coffee */
/* yarr */
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.bgimage {
width: 100%;
height: 100%;
position: absolute;
left:0;
top:0;
pointer-events: none;
background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 28" width="112" height="56"%3E%3Cpath fill="%239C92AC" fill-opacity="0.4" d="M56 26v2h-7.75c2.3-1.27 4.94-2 7.75-2zm-26 2a2 2 0 1 0-4 0h-4.09A25.98 25.98 0 0 0 0 16v-2c.67 0 1.34.02 2 .07V14a2 2 0 0 0-2-2v-2a4 4 0 0 1 3.98 3.6 28.09 28.09 0 0 1 2.8-3.86A8 8 0 0 0 0 6V4a9.99 9.99 0 0 1 8.17 4.23c.94-.95 1.96-1.83 3.03-2.63A13.98 13.98 0 0 0 0 0h7.75c2 1.1 3.73 2.63 5.1 4.45 1.12-.72 2.3-1.37 3.53-1.93A20.1 20.1 0 0 0 14.28 0h2.7c.45.56.88 1.14 1.29 1.74 1.3-.48 2.63-.87 4-1.15-.11-.2-.23-.4-.36-.59H26v.07a28.4 28.4 0 0 1 4 0V0h4.09l-.37.59c1.38.28 2.72.67 4.01 1.15.4-.6.84-1.18 1.3-1.74h2.69a20.1 20.1 0 0 0-2.1 2.52c1.23.56 2.41 1.2 3.54 1.93A16.08 16.08 0 0 1 48.25 0H56c-4.58 0-8.65 2.2-11.2 5.6 1.07.8 2.09 1.68 3.03 2.63A9.99 9.99 0 0 1 56 4v2a8 8 0 0 0-6.77 3.74c1.03 1.2 1.97 2.5 2.79 3.86A4 4 0 0 1 56 10v2a2 2 0 0 0-2 2.07 28.4 28.4 0 0 1 2-.07v2c-9.2 0-17.3 4.78-21.91 12H30zM7.75 28H0v-2c2.81 0 5.46.73 7.75 2zM56 20v2c-5.6 0-10.65 2.3-14.28 6h-2.7c4.04-4.89 10.15-8 16.98-8zm-39.03 8h-2.69C10.65 24.3 5.6 22 0 22v-2c6.83 0 12.94 3.11 16.97 8zm15.01-.4a28.09 28.09 0 0 1 2.8-3.86 8 8 0 0 0-13.55 0c1.03 1.2 1.97 2.5 2.79 3.86a4 4 0 0 1 7.96 0zm14.29-11.86c1.3-.48 2.63-.87 4-1.15a25.99 25.99 0 0 0-44.55 0c1.38.28 2.72.67 4.01 1.15a21.98 21.98 0 0 1 36.54 0zm-5.43 2.71c1.13-.72 2.3-1.37 3.54-1.93a19.98 19.98 0 0 0-32.76 0c1.23.56 2.41 1.2 3.54 1.93a15.98 15.98 0 0 1 25.68 0zm-4.67 3.78c.94-.95 1.96-1.83 3.03-2.63a13.98 13.98 0 0 0-22.4 0c1.07.8 2.09 1.68 3.03 2.63a9.99 9.99 0 0 1 16.34 0z"%3E%3C/path%3E%3C/svg%3E') !important;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment