Skip to content

Commit 4d5a5b7

Browse files
authored
Updated challenges and solution page (#87)
* Updated langind page and pagination for challenges page * Updated the admin dashboard * Updated challenge and solution page
1 parent ca78a29 commit 4d5a5b7

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

client-test/src/components/Challenges/index.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const Challenges: React.FC = () => {
5555
platforms: []
5656
});
5757
const itemsPerPage = 5;
58-
const { user } = useAuth();
58+
const { user, isAuthenticated } = useAuth();
5959

6060
// Debounced search function
6161
const useDebounce = (value: string, delay: number) => {
@@ -289,6 +289,11 @@ const Challenges: React.FC = () => {
289289

290290
const checkPotdSolved = async () => {
291291
setIsRefreshing(true);
292+
if(!isAuthenticated) {
293+
toast.error("Please login to check status");
294+
setIsRefreshing(false)
295+
return;
296+
}
292297
try {
293298
const response = await axios.post(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/check-potd-status`, {
294299
dailyChallengeId: dailyProblem?._id
@@ -304,7 +309,7 @@ const Challenges: React.FC = () => {
304309
}
305310
} catch (error: any) {
306311
console.error("Error updating POTD status:", error);
307-
toast.error("Challenge NOT solved Today");
312+
toast.error("Challenge not solved today");
308313
} finally {
309314
setIsRefreshing(false);
310315
}
@@ -340,7 +345,16 @@ const Challenges: React.FC = () => {
340345
};
341346

342347
// Open challenge link in a new tab
343-
const openProblemLink = (url?: string) => url && window.open(url, "_blank");
348+
const openProblemLink = (url?: string) => {
349+
if(!isAuthenticated) {
350+
toast.error("Please login to open problem");
351+
return;
352+
} else {
353+
if(url) {
354+
window.open(url, "_blank")
355+
}
356+
}
357+
};
344358

345359
return (
346360
<div className="w-full max-w-[1040px] mx-auto px-4 py-5 space-y-8 min-h-screen">

client-test/src/components/Challenges/solutionPage.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface SolutionData {
2222
description: string;
2323
category: string[];
2424
problemLink: string;
25+
solved?: boolean;
2526
codeSnippets: {
2627
explanation: string;
2728
python: string;
@@ -163,6 +164,21 @@ const CategoryPill: React.FC<{ category: string; index: number }> = ({ category,
163164
);
164165
};
165166

167+
// Solved Status Badge component
168+
const SolvedBadge: React.FC = () => {
169+
return (
170+
<motion.div
171+
initial={{ scale: 0.8, opacity: 0 }}
172+
animate={{ scale: 1, opacity: 1 }}
173+
transition={{ duration: 0.3, delay: 0.2 }}
174+
className="flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-green-500/10 text-green-600 border border-green-500/20"
175+
>
176+
<Check className="h-3.5 w-3.5" />
177+
<span className="text-xs font-medium">Solved</span>
178+
</motion.div>
179+
);
180+
};
181+
166182
const SolutionPage: React.FC = () => {
167183
const location = useLocation();
168184
const navigate = useNavigate();
@@ -207,7 +223,6 @@ const SolutionPage: React.FC = () => {
207223
}
208224

209225
const data: SolutionData = response.data;
210-
console.log("data", data);
211226
if (data) {
212227
setSolution(data);
213228
} else {
@@ -281,10 +296,13 @@ const SolutionPage: React.FC = () => {
281296
<div className="p-1.5 sm:p-2 rounded-xl bg-primary/10 dark:bg-primary/20 shadow-inner border border-primary/10">
282297
<TerminalSquare className="h-5 w-5 sm:h-6 sm:w-6 text-primary" />
283298
</div>
284-
<div>
285-
<h1 className="text-xl sm:text-2xl font-bold text-foreground">
286-
{solution.title}
287-
</h1>
299+
<div className="flex-1">
300+
<div className="flex items-center gap-2 flex-wrap">
301+
<h1 className="text-xl sm:text-2xl font-bold text-foreground">
302+
{solution.title}
303+
</h1>
304+
{solution.solved && <SolvedBadge />}
305+
</div>
288306
<p className="text-xs sm:text-sm text-muted-foreground">Solution Explorer</p>
289307
</div>
290308
</motion.div>

server/controllers/challengeController.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export const getChallenges = async (req, res) => {
4848
if (search && search.trim()) {
4949
filter.$or = [
5050
{ title: { $regex: search.trim(), $options: 'i' } },
51-
{ description: { $regex: search.trim(), $options: 'i' } },
5251
{ category: { $regex: search.trim(), $options: 'i' } }
5352
];
5453
}
@@ -202,17 +201,31 @@ export const getChallengeById = async (req, res) => {
202201
export const getSolutionByChallengeId = async (req, res) => {
203202
try {
204203
const { id } = req.params;
204+
const authenticatedUser = req.user;
205205

206206
const solution = await Solution.findOne({ challenge: id })
207207
.populate('challenge', 'title description category problemLink')
208208
.select('-_id -__v');
209209

210210
if (solution) {
211+
// Check if user has solved this challenge
212+
let isSolved = false;
213+
if (authenticatedUser) {
214+
const solvedChallengeIds = [
215+
...(authenticatedUser.solveChallenges?.easy || []).map(item => item.challenge?.toString()),
216+
...(authenticatedUser.solveChallenges?.medium || []).map(item => item.challenge?.toString()),
217+
...(authenticatedUser.solveChallenges?.hard || []).map(item => item.challenge?.toString())
218+
].filter(Boolean);
219+
220+
isSolved = solvedChallengeIds.includes(id);
221+
}
222+
211223
const formattedSolution = {
212224
title: solution.challenge.title,
213225
description: solution.challenge.description,
214226
category: solution.challenge.category,
215227
problemLink: solution.challenge.problemLink,
228+
solved: isSolved,
216229
codeSnippets: {
217230
explanation: solution.explanation,
218231
python: solution.python,

0 commit comments

Comments
 (0)