-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from winglang/rybickic/website-skeleton
- Loading branch information
Showing
8 changed files
with
181 additions
and
78 deletions.
There are no files selected for viewing
This file contains 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import React, { useState, useEffect } from "react"; | ||
|
||
interface Config { | ||
baseUrl: string; | ||
} | ||
|
||
interface Entry { | ||
name: string; | ||
score: number; | ||
} | ||
|
||
const fetchConfig = async () => { | ||
const response = await fetch("./config.json"); | ||
if (!response.ok) { | ||
throw new Error('Failed to fetch config'); | ||
} | ||
const config: Config = await response.json(); | ||
return config; | ||
} | ||
|
||
const fetchItems = async () => { | ||
const baseUrl = (await fetchConfig()).baseUrl; | ||
const response = await fetch(baseUrl + "/items"); | ||
if (!response.ok) { | ||
throw new Error('Failed to fetch leaderboard data'); | ||
} | ||
const jsonData: Entry[] = await response.json(); | ||
return jsonData; | ||
} | ||
|
||
const fetchChoices = async () => { | ||
const baseUrl = (await fetchConfig()).baseUrl; | ||
const response = await fetch(baseUrl + "/requestChoices", { | ||
method: "POST", | ||
}); | ||
if (!response.ok) { | ||
throw new Error('Failed to request choices'); | ||
} | ||
const jsonData: string[] = await response.json(); | ||
return jsonData; | ||
} | ||
|
||
interface LeaderboardProps { | ||
swapViews: () => void; | ||
} | ||
|
||
const Leaderboard = (props: LeaderboardProps) => { | ||
const [data, setData] = useState<Entry[]>([]); | ||
useEffect(() => { | ||
fetchItems().then((items) => setData(items)); | ||
}, []); | ||
|
||
return ( | ||
<div> | ||
<h2>Leaderboard</h2> | ||
<table> | ||
<thead> | ||
<tr> | ||
<th>Name</th> | ||
<th>Score</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{data.sort((a, b) => b.score - a.score).map((item) => ( | ||
<tr key={item.name}> | ||
<td>{item.name}</td> | ||
<td>{item.score}</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
<button onClick={props.swapViews}>Back</button> | ||
</div> | ||
); | ||
}; | ||
|
||
interface VotingProps { | ||
swapViews: () => void; | ||
} | ||
|
||
const Voting = (props: VotingProps) => { | ||
const [choices, setChoices] = useState<string[]>([]); | ||
useEffect(() => { | ||
fetchChoices().then((choices) => setChoices(choices)); | ||
}, []); | ||
|
||
return ( | ||
<div> | ||
<h2>Which is better?</h2> | ||
<div className="choices"> | ||
{choices.map((item) => ( | ||
<div key={item} className="choice"> | ||
<div className="name">{item}</div> | ||
<button className="button">Vote</button> | ||
</div> | ||
))} | ||
</div> | ||
<button onClick={props.swapViews}>Leaderboard</button> | ||
</div> | ||
) | ||
} | ||
|
||
type View = "voting" | "leaderboard"; | ||
|
||
function App() { | ||
let [view, setView] = useState<View>("voting"); | ||
const swapViews = () => { | ||
setView(view === "voting" ? "leaderboard" : "voting"); | ||
}; | ||
|
||
switch (view) { | ||
case "voting": | ||
return <Voting swapViews={swapViews} />; | ||
case "leaderboard": | ||
return <Leaderboard swapViews={swapViews} />; | ||
} | ||
} | ||
|
||
export default App; |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "es5", | ||
"lib": [ | ||
"dom", | ||
"dom.iterable", | ||
"esnext" | ||
], | ||
"allowJs": true, | ||
"skipLibCheck": true, | ||
"esModuleInterop": true, | ||
"allowSyntheticDefaultImports": true, | ||
"strict": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"module": "esnext", | ||
"moduleResolution": "node", | ||
"resolveJsonModule": true, | ||
"isolatedModules": true, | ||
"noEmit": true, | ||
"jsx": "react-jsx" | ||
}, | ||
"include": [ | ||
"src" | ||
] | ||
} |