mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-01 21:32:35 +02:00
Add reset progress functionality
This commit is contained in:
@@ -11,10 +11,12 @@ import { useToast } from '../../hooks/use-toast';
|
|||||||
|
|
||||||
type UserQuestionProgress = {
|
type UserQuestionProgress = {
|
||||||
know: string[];
|
know: string[];
|
||||||
didNotKnow: string[];
|
dontKnow: string[];
|
||||||
skipped: string[];
|
skip: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ProgressType = keyof UserQuestionProgress;
|
||||||
|
|
||||||
type QuestionsListProps = {
|
type QuestionsListProps = {
|
||||||
groupId: string;
|
groupId: string;
|
||||||
questions: QuestionType[];
|
questions: QuestionType[];
|
||||||
@@ -70,14 +72,14 @@ export function QuestionsList(props: QuestionsListProps) {
|
|||||||
setUserProgress(userProgress);
|
setUserProgress(userProgress);
|
||||||
|
|
||||||
const knownQuestions = userProgress?.know || [];
|
const knownQuestions = userProgress?.know || [];
|
||||||
const didNotKnowQuestions = userProgress?.didNotKnow || [];
|
const didNotKnowQuestions = userProgress?.dontKnow || [];
|
||||||
const skippedQuestions = userProgress?.skipped || [];
|
const skipQuestions = userProgress?.skip || [];
|
||||||
|
|
||||||
const pendingQuestions = unshuffledQuestions.filter((question) => {
|
const pendingQuestions = unshuffledQuestions.filter((question) => {
|
||||||
return (
|
return (
|
||||||
!knownQuestions.includes(question.id) &&
|
!knownQuestions.includes(question.id) &&
|
||||||
!didNotKnowQuestions.includes(question.id) &&
|
!didNotKnowQuestions.includes(question.id) &&
|
||||||
!skippedQuestions.includes(question.id)
|
!skipQuestions.includes(question.id)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -88,20 +90,75 @@ export function QuestionsList(props: QuestionsListProps) {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resetProgress(type: ProgressType | 'all' = 'all') {
|
||||||
|
let knownQuestions = userProgress?.know || [];
|
||||||
|
let didNotKnowQuestions = userProgress?.dontKnow || [];
|
||||||
|
let skipQuestions = userProgress?.skip || [];
|
||||||
|
|
||||||
|
if (!isLoggedIn()) {
|
||||||
|
if (type === 'know') {
|
||||||
|
knownQuestions = [];
|
||||||
|
} else if (type === 'dontKnow') {
|
||||||
|
didNotKnowQuestions = [];
|
||||||
|
} else if (type === 'skip') {
|
||||||
|
skipQuestions = [];
|
||||||
|
} else if (type === 'all') {
|
||||||
|
knownQuestions = [];
|
||||||
|
didNotKnowQuestions = [];
|
||||||
|
skipQuestions = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const { response, error } = await httpPut<UserQuestionProgress>(
|
||||||
|
`/v1-reset-question-progress/${groupId}`,
|
||||||
|
{
|
||||||
|
type,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
toast.error(error.message || 'Error resetting progress');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
knownQuestions = response?.know || [];
|
||||||
|
didNotKnowQuestions = response?.dontKnow || [];
|
||||||
|
skipQuestions = response?.skip || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingQuestions = unshuffledQuestions.filter((question) => {
|
||||||
|
return (
|
||||||
|
!knownQuestions.includes(question.id) &&
|
||||||
|
!didNotKnowQuestions.includes(question.id) &&
|
||||||
|
!skipQuestions.includes(question.id)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
setUserProgress({
|
||||||
|
know: knownQuestions,
|
||||||
|
dontKnow: didNotKnowQuestions,
|
||||||
|
skip: skipQuestions,
|
||||||
|
});
|
||||||
|
|
||||||
|
setPendingQuestions(pendingQuestions.sort(() => Math.random() - 0.5));
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
|
||||||
async function updateQuestionStatus(
|
async function updateQuestionStatus(
|
||||||
status: 'know' | 'dontKnow' | 'skip',
|
status: ProgressType,
|
||||||
questionId: string
|
questionId: string
|
||||||
) {
|
) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
let newProgress = userProgress || { know: [], didNotKnow: [], skipped: [] };
|
let newProgress = userProgress || { know: [], dontKnow: [], skip: [] };
|
||||||
|
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
if (status === 'know') {
|
if (status === 'know') {
|
||||||
newProgress.know.push(questionId);
|
newProgress.know.push(questionId);
|
||||||
} else if (status == 'dontKnow') {
|
} else if (status == 'dontKnow') {
|
||||||
newProgress.didNotKnow.push(questionId);
|
newProgress.dontKnow.push(questionId);
|
||||||
} else if (status == 'skip') {
|
} else if (status == 'skip') {
|
||||||
newProgress.skipped.push(questionId);
|
newProgress.skip.push(questionId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { response, error } = await httpPut<UserQuestionProgress>(
|
const { response, error } = await httpPut<UserQuestionProgress>(
|
||||||
@@ -130,10 +187,10 @@ export function QuestionsList(props: QuestionsListProps) {
|
|||||||
loadQuestions().then(() => null);
|
loadQuestions().then(() => null);
|
||||||
}, [unshuffledQuestions]);
|
}, [unshuffledQuestions]);
|
||||||
|
|
||||||
const knownCount = userProgress?.know.length || 0;
|
const knowCount = userProgress?.know.length || 0;
|
||||||
const didNotKnowCount = userProgress?.didNotKnow.length || 0;
|
const dontKnowCount = userProgress?.dontKnow.length || 0;
|
||||||
const skippedCount = userProgress?.skipped.length || 0;
|
const skipCount = userProgress?.skip.length || 0;
|
||||||
const hasProgress = knownCount > 0 || didNotKnowCount > 0 || skippedCount > 0;
|
const hasProgress = knowCount > 0 || dontKnowCount > 0 || skipCount > 0;
|
||||||
|
|
||||||
const currQuestion = pendingQuestions[0];
|
const currQuestion = pendingQuestions[0];
|
||||||
|
|
||||||
@@ -147,12 +204,15 @@ export function QuestionsList(props: QuestionsListProps) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<QuestionsProgress
|
<QuestionsProgress
|
||||||
knowCount={knownCount}
|
knowCount={knowCount}
|
||||||
didNotKnowCount={didNotKnowCount}
|
didNotKnowCount={dontKnowCount}
|
||||||
skippedCount={skippedCount}
|
skippedCount={skipCount}
|
||||||
totalCount={unshuffledQuestions?.length || questions?.length}
|
totalCount={unshuffledQuestions?.length || questions?.length}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
showLoginAlert={!isLoggedIn() && hasProgress}
|
showLoginAlert={!isLoggedIn() && hasProgress}
|
||||||
|
onResetClick={() => {
|
||||||
|
resetProgress('all').finally(() => null);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="relative mb-4 flex min-h-[400px] w-full overflow-hidden rounded-lg border border-gray-300 bg-white">
|
<div className="relative mb-4 flex min-h-[400px] w-full overflow-hidden rounded-lg border border-gray-300 bg-white">
|
||||||
|
@@ -8,6 +8,7 @@ type QuestionsProgressProps = {
|
|||||||
didNotKnowCount?: number;
|
didNotKnowCount?: number;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
skippedCount?: number;
|
skippedCount?: number;
|
||||||
|
onResetClick?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function QuestionsProgress(props: QuestionsProgressProps) {
|
export function QuestionsProgress(props: QuestionsProgressProps) {
|
||||||
@@ -18,6 +19,7 @@ export function QuestionsProgress(props: QuestionsProgressProps) {
|
|||||||
didNotKnowCount = 0,
|
didNotKnowCount = 0,
|
||||||
totalCount = 0,
|
totalCount = 0,
|
||||||
skippedCount = 0,
|
skippedCount = 0,
|
||||||
|
onResetClick = () => null,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const totalSolved = knowCount + didNotKnowCount + skippedCount;
|
const totalSolved = knowCount + didNotKnowCount + skippedCount;
|
||||||
@@ -64,7 +66,11 @@ export function QuestionsProgress(props: QuestionsProgressProps) {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button className="flex items-center text-red-600 hover:text-red-900">
|
<button
|
||||||
|
disabled={isLoading}
|
||||||
|
onClick={onResetClick}
|
||||||
|
className="flex items-center text-red-600 transition-opacity duration-300 hover:text-red-900 disabled:opacity-50"
|
||||||
|
>
|
||||||
<RotateCcw className="mr-1 h-4" />
|
<RotateCcw className="mr-1 h-4" />
|
||||||
Reset
|
Reset
|
||||||
</button>
|
</button>
|
||||||
|
Reference in New Issue
Block a user