fixing progress bar on game sections

This commit is contained in:
adueck 2024-07-08 15:34:50 -04:00
parent 9a6cd29af6
commit b0ed40fb07
1 changed files with 109 additions and 87 deletions

View File

@ -4,108 +4,130 @@ import { useUser } from "../user-context";
import Link from "../components/Link"; import Link from "../components/Link";
// @ts-ignore // @ts-ignore
import SmoothCollapse from "react-smooth-collapse"; import SmoothCollapse from "react-smooth-collapse";
import { import { AT } from "@lingdocs/lingdocs-main";
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 handleChapterClick(id: string) { function handleChapterClick(id: string) {
setOpened(prev => prev === id ? undefined : id); setOpened((prev) => (prev === id ? undefined : id));
} }
return <div> return (
{games.map((chapter) => ( <div>
<div key={chapter.chapter}> {games.map((chapter) => (
<ChapterDisplay <div key={chapter.chapter}>
chapter={chapter} <ChapterDisplay
user={user} chapter={chapter}
handleClick={handleChapterClick} user={user}
expanded={opened === chapter.chapter} handleClick={handleChapterClick}
/> expanded={opened === chapter.chapter}
</div> />
))} </div>
))}
</div> </div>
);
} }
function ChapterDisplay({ chapter, user, handleClick, expanded }: { function ChapterDisplay({
chapter: { chapter: string, items: GameRecord[] }, chapter,
user: AT.LingdocsUser | undefined, user,
handleClick: (chapter: string) => void, handleClick,
expanded: boolean, expanded,
}: {
chapter: { chapter: string; items: GameRecord[] };
user: AT.LingdocsUser | undefined;
handleClick: (chapter: string) => void;
expanded: boolean;
}) { }) {
const [opened, setOpened] = useState<string | undefined>(undefined); const [opened, setOpened] = useState<string | undefined>(undefined);
const progress = getPercentageComplete(chapter, user?.tests); const progress = getPercentageComplete(chapter, user?.tests);
function handleTitleClick(id: string) { function handleTitleClick(id: string) {
setOpened(prev => prev === id ? undefined : id); setOpened((prev) => (prev === id ? undefined : id));
} }
return <div className="mb-3"> return (
<div className="card clickable" onClick={() => handleClick(chapter.chapter)}> <div className="mb-3">
<div className="card-body" style={{ <div
backgroundColor: expanded ? "#e6e6e6" : "inherit", className="card clickable"
}}> onClick={() => handleClick(chapter.chapter)}
<h4>{chapter.chapter}</h4> >
<ChapterProgress progress={progress} /> <div
</div> className="card-body"
style={{
backgroundColor: expanded ? "#e6e6e6" : "inherit",
}}
>
<h4>{chapter.chapter}</h4>
<ChapterProgress progress={progress} />
</div> </div>
<SmoothCollapse expanded={expanded}> </div>
{chapter.items.map(({ id, title, Game }) => { <SmoothCollapse expanded={expanded}>
const done = user?.tests.some(t => t.done && t.id === id); {chapter.items.map(({ id, title, Game }) => {
const open = opened === id; const done = user?.tests.some((t) => t.done && t.id === id);
return <div key={id}> const open = opened === id;
<div className="d-flex flex-row justify-content-between align-items-center"> return (
<div> <div key={id}>
<h5 className="my-3 clickable" onClick={() => handleTitleClick(id)}> <div className="d-flex flex-row justify-content-between align-items-center">
<i className={`fas fa-caret-${open ? "down" : "right"}`}></i> {title} <div>
{` `} <h5
</h5> className="my-3 clickable"
</div> onClick={() => handleTitleClick(id)}
<div> >
{done && <h4></h4>} <i
</div> className={`fas fa-caret-${open ? "down" : "right"}`}
</div> ></i>{" "}
<SmoothCollapse expanded={open}> {title}
{open && <Game inChapter={false} />} {` `}
</SmoothCollapse> </h5>
</div> </div>
})} <div>{done && <h4></h4>}</div>
</SmoothCollapse> </div>
<SmoothCollapse expanded={open}>
{open && <Game inChapter={false} />}
</SmoothCollapse>
</div>
);
})}
</SmoothCollapse>
</div> </div>
);
} }
function ChapterProgress({ progress }: { progress: "not logged in" | number }) { function ChapterProgress({ progress }: { progress: "not logged in" | number }) {
if (progress === "not logged in") { if (progress === "not logged in") {
return <div className="small text-muted"><Link to="/account">Log in</Link> to see progress</div>; return (
} <div className="small text-muted">
return <div> <Link to="/account">Log in</Link> to see progress
<div className="small text-muted">{progress}% mastered</div> </div>
<div className="progress my-1" style={{ height: "5px" }}> );
<div }
className="progress-bar" return (
role="progressbar" <div>
style={{ width: `${progress}%` }} <div className="small text-muted">{progress}% mastered</div>
/> <div className="progress my-1" style={{ height: "5px" }}>
</div> <div
</div>; className="progress-bar"
role="progressbar"
style={{ width: `${progress}%` }}
/>
</div>
</div>
);
} }
function getPercentageComplete( function getPercentageComplete(
chapter: { chapter: string, items: GameRecord[] }, chapter: { chapter: string; items: GameRecord[] },
tests: undefined | AT.TestResult[], tests: undefined | AT.TestResult[]
): "not logged in" | number { ): "not logged in" | number {
if (!tests) return "not logged in"; if (!tests) return "not logged in";
const chapterTestIds = chapter.items.map(gr => gr.id); const chapterTestIds = chapter.items.map((gr) => gr.id);
const userCompletedIds = tests.filter(t => t.done).map(t => t.id); const userCompletedIds = tests.filter((t) => t.done).map((t) => t.id);
const required = chapterTestIds.length; const required = chapterTestIds.length;
const completed = chapterTestIds const completed = chapterTestIds.filter((x) =>
.filter(x => userCompletedIds.includes(x)) userCompletedIds.includes(x)
.length; ).length;
return Math.round( return Math.round((completed / required) * 100);
(completed / (required + 1)) * 100
);
} }
export default GamesBrowser; export default GamesBrowser;