Show user progress

pull/4448/head
Kamran Ahmed 1 year ago
parent 548b7f31f9
commit a847d0b08d
  1. 43
      src/components/Questions/QuestionsList.tsx
  2. 47
      src/components/Questions/QuestionsProgress.tsx

@ -12,6 +12,7 @@ import { useToast } from '../../hooks/use-toast';
type UserQuestionProgress = {
know: string[];
didNotKnow: string[];
skipped: string[];
};
type QuestionsListProps = {
@ -20,13 +21,11 @@ type QuestionsListProps = {
};
export function QuestionsList(props: QuestionsListProps) {
const { questions: defaultQuestions, groupId } = props;
const { questions: unshuffledQuestions, groupId } = props;
const toast = useToast();
const [isLoading, setIsLoading] = useState(true);
const [isUpdatingStatus, setIsUpdatingStatus] = useState(false);
const [confettiEl, setConfettiEl] = useState<HTMLElement | null>(null);
const [questions, setQuestions] = useState<QuestionType[]>();
@ -72,33 +71,37 @@ export function QuestionsList(props: QuestionsListProps) {
const knownQuestions = userProgress?.know || [];
const didNotKnowQuestions = userProgress?.didNotKnow || [];
const skippedQuestions = userProgress?.skipped || [];
const pendingQuestions = defaultQuestions.filter((question) => {
const pendingQuestions = unshuffledQuestions.filter((question) => {
return (
!knownQuestions.includes(question.id) &&
!didNotKnowQuestions.includes(question.id)
!didNotKnowQuestions.includes(question.id) &&
!skippedQuestions.includes(question.id)
);
});
// Shuffle and set pending questions
setPendingQuestions(pendingQuestions.sort(() => Math.random() - 0.5));
setQuestions(defaultQuestions);
setQuestions(unshuffledQuestions);
setIsLoading(false);
}
async function updateQuestionStatus(
status: 'know' | 'dontKnow',
status: 'know' | 'dontKnow' | 'skip',
questionId: string
) {
setIsUpdatingStatus(true);
let newProgress = userProgress || { know: [], didNotKnow: [] };
setIsLoading(true);
let newProgress = userProgress || { know: [], didNotKnow: [], skipped: [] };
if (!isLoggedIn()) {
if (status === 'know') {
newProgress.know.push(questionId);
} else {
} else if (status == 'dontKnow') {
newProgress.didNotKnow.push(questionId);
} else if (status == 'skip') {
newProgress.skipped.push(questionId);
}
} else {
const { response, error } = await httpPut<UserQuestionProgress>(
@ -120,16 +123,17 @@ export function QuestionsList(props: QuestionsListProps) {
setUserProgress(newProgress);
setPendingQuestions(pendingQuestions.filter((q) => q.id !== questionId));
setIsUpdatingStatus(false);
setIsLoading(false);
}
useEffect(() => {
loadQuestions().then(() => null);
}, [defaultQuestions]);
}, [unshuffledQuestions]);
const knownCount = userProgress?.know.length || 0;
const didNotKnowCount = userProgress?.didNotKnow.length || 0;
const hasProgress = knownCount > 0 || didNotKnowCount > 0;
const skippedCount = userProgress?.skipped.length || 0;
const hasProgress = knownCount > 0 || didNotKnowCount > 0 || skippedCount > 0;
const currQuestion = pendingQuestions[0];
@ -143,6 +147,10 @@ export function QuestionsList(props: QuestionsListProps) {
/>
<QuestionsProgress
knowCount={knownCount}
didNotKnowCount={didNotKnowCount}
skippedCount={skippedCount}
totalCount={unshuffledQuestions?.length || questions?.length}
isLoading={isLoading}
showLoginAlert={!isLoggedIn() && hasProgress}
/>
@ -154,7 +162,7 @@ export function QuestionsList(props: QuestionsListProps) {
<div className="flex flex-col gap-3 sm:flex-row">
<button
disabled={isLoading || isUpdatingStatus}
disabled={isLoading}
ref={alreadyKnowRef}
onClick={(e) => {
showConfetti(alreadyKnowRef.current);
@ -173,14 +181,17 @@ export function QuestionsList(props: QuestionsListProps) {
() => null
);
}}
disabled={isLoading || isUpdatingStatus}
disabled={isLoading}
className="flex flex-1 items-center rounded-xl border border-gray-300 bg-white py-3 px-4 text-black transition-colors hover:border-black hover:bg-black hover:text-white disabled:pointer-events-none disabled:opacity-50"
>
<Sparkles className="mr-1 h-4 text-current" />
Didn't Know that
</button>
<button
disabled={isLoading || isUpdatingStatus}
onClick={() => {
updateQuestionStatus('skip', currQuestion.id).finally(() => null);
}}
disabled={isLoading}
data-next-question="skip"
className="flex flex-1 items-center rounded-xl border border-red-600 p-3 text-red-600 hover:bg-red-600 hover:text-white disabled:pointer-events-none disabled:opacity-50"
>

@ -1,43 +1,72 @@
import { CheckCircle, RotateCcw, Sparkles } from 'lucide-react';
import { CheckCircle, RotateCcw, SkipForward, Sparkles } from 'lucide-react';
import { showLoginPopup } from '../../lib/popup';
type QuestionsProgressProps = {
isLoading?: boolean;
showLoginAlert?: boolean;
knowCount?: number;
didNotKnowCount?: number;
totalCount?: number;
skippedCount?: number;
};
export function QuestionsProgress(props: QuestionsProgressProps) {
const { showLoginAlert, isLoading = false } = props;
const {
showLoginAlert,
isLoading = false,
knowCount = 0,
didNotKnowCount = 0,
totalCount = 0,
skippedCount = 0,
} = props;
const totalSolved = knowCount + didNotKnowCount + skippedCount;
const donePercentage = (totalSolved / totalCount) * 100;
return (
<div className="mb-5 overflow-hidden rounded-lg border border-gray-300 bg-white p-6">
<div className="mb-3 flex items-center text-gray-600">
<div className="relative w-full flex-1 rounded-xl bg-gray-200 p-1">
<div className="absolute bottom-0 left-0 top-0 w-[30%] rounded-xl bg-slate-800"></div>
<div
className="absolute bottom-0 left-0 top-0 rounded-xl bg-slate-800"
style={{
width: `${donePercentage}%`,
}}
/>
</div>
<span className="ml-3 text-sm">5 / 100</span>
<span className="ml-3 text-sm">
{totalSolved} / {totalCount}
</span>
</div>
<div className="relative -left-1 flex flex-col gap-2 text-sm text-black sm:flex-row sm:gap-3">
<span className="flex items-center">
<CheckCircle className="mr-1 h-4" />
<span>Already knew</span>
<span>Knew</span>
<span className="ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black">
44 Questions
{knowCount} Questions
</span>
</span>
<span className="flex items-center">
<Sparkles className="mr-1 h-4" />
<span>Didn't Know</span>
<span>Learnt</span>
<span className="ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black">
{didNotKnowCount} Questions
</span>
</span>
<span className="flex items-center">
<SkipForward className="mr-1 h-4" />
<span>Skipped</span>
<span className="ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black">
20 Questions
{skippedCount} Questions
</span>
</span>
<button className="flex items-center text-red-600 hover:text-red-900">
<RotateCcw className="mr-1 h-4" />
Reset Progress
Reset
</button>
</div>

Loading…
Cancel
Save