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