A Pen by shamsheer Bali on CodePen.
Created
December 13, 2024 04:16
-
-
Save shmshrbali/28889697ff317107d766396a6062ff02 to your computer and use it in GitHub Desktop.
Kamo's Quiz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div id="app"></div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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")); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* 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