fixing progress bar on game sections
This commit is contained in:
parent
9a6cd29af6
commit
b0ed40fb07
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue