better games browser with section progress

This commit is contained in:
lingdocs 2022-08-29 19:42:55 +04:00
parent 4583e733fa
commit a3219230bc
1 changed files with 96 additions and 27 deletions

View File

@ -3,11 +3,14 @@ import games from "./games";
import { useUser } from "../user-context"; import { useUser } from "../user-context";
import Link from "../components/Link"; import Link from "../components/Link";
import SmoothCollapse from "react-smooth-collapse"; import SmoothCollapse from "react-smooth-collapse";
import {
AT,
} from "@lingdocs/lingdocs-main";
function GamesBrowser() { function GamesBrowser() {
const { user } = useUser(); const { user } = useUser();
const [opened, setOpened] = useState<string | undefined>(undefined); const [opened, setOpened] = useState<string | undefined>(undefined);
function handleTitleClick(id: string) { function handleChapterClick(id: string) {
setOpened(prev => ( setOpened(prev => (
prev === id ? undefined : id prev === id ? undefined : id
)); ));
@ -15,7 +18,40 @@ function GamesBrowser() {
return <div> return <div>
{games.map((chapter) => ( {games.map((chapter) => (
<div key={chapter.chapter}> <div key={chapter.chapter}>
<h3>{chapter.chapter}</h3> <ChapterDisplay
chapter={chapter}
user={user}
handleClick={handleChapterClick}
expanded={opened === chapter.chapter}
/>
</div>
))}
</div>
}
function ChapterDisplay({ chapter, user, handleClick, expanded }: {
chapter: { chapter: string, items: GameRecord[] },
user: AT.LingdocsUser | undefined,
handleClick: (chapter: string) => void,
expanded: boolean,
}) {
const [opened, setOpened] = useState<string | undefined>(undefined);
const progress = getPercentageComplete(chapter, user?.tests);
function handleTitleClick(id: string) {
setOpened(prev => (
prev === id ? undefined : id
));
}
return <div className="mb-3">
<div className="card clickable" onClick={() => handleClick(chapter.chapter)}>
<div className="card-body" style={{
backgroundColor: expanded ? "#e6e6e6" : "inherit",
}}>
<h4>{chapter.chapter}</h4>
<ChapterProgress progress={progress} />
</div>
</div>
<SmoothCollapse expanded={expanded}>
{chapter.items.map(({ id, title, Game, studyLink }) => { {chapter.items.map(({ id, title, Game, studyLink }) => {
const done = user && user.tests.some(t => t.id === id); const done = user && user.tests.some(t => t.id === id);
const open = opened === id; const open = opened === id;
@ -41,9 +77,42 @@ function GamesBrowser() {
</SmoothCollapse> </SmoothCollapse>
</div> </div>
})} })}
</SmoothCollapse>
</div> </div>
))}
}
function ChapterProgress({ progress }: { progress: "not logged in" | number }) {
if (progress === "not logged in") {
return <div className="small text-muted">Log in to see progress</div>;
}
return <div>
<div className="small text-muted">{progress}% mastered</div>
<div className="progress my-1" style={{ height: "5px" }}>
<div
className="progress-bar"
role="progressbar"
style={{ width: `${progress}%` }}
/>
</div> </div>
</div>;
}
function getPercentageComplete(
chapter: { chapter: string, items: GameRecord[] },
tests: undefined | AT.TestResult[],
): "not logged in" | number {
if (!tests) return "not logged in";
const chapterTestIds = chapter.items.map(gr => gr.id);
const userCompletedIds = tests.map(t => t.id);
const required = chapterTestIds.length;
const completed = chapterTestIds
.filter(userCompletedIds.includes)
.length;
return Math.round(
(completed / (required + 1)) * 100
);
} }
export default GamesBrowser; export default GamesBrowser;