From 06809cd08bc93baea9df00504dfc67ff26d5a42f Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 1 May 2026 21:08:40 +0530 Subject: [PATCH 1/2] changed description from min string 10 to 0 --- .gitignore | 1 + client/src/pages/Dashboard.jsx | 43 ++++++------- client/src/pages/Leaderboard.jsx | 90 +++++++++++++++++++++++---- client/src/pages/Missions.jsx | 10 ++- server/validators/challengeSchemas.js | 2 +- 5 files changed, 105 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 81e83fe..e6a3755 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules .vercel + diff --git a/client/src/pages/Dashboard.jsx b/client/src/pages/Dashboard.jsx index 5681459..69ef636 100644 --- a/client/src/pages/Dashboard.jsx +++ b/client/src/pages/Dashboard.jsx @@ -57,8 +57,8 @@ const Dashboard = () => { const recentActivity = summaryQuery.data?.recentActivity?.length ? summaryQuery.data.recentActivity : MOCK_ACTIVITY; const solvedRate = summaryQuery.data?.totalChallenges ? Math.round( - (summaryQuery.data.solved / summaryQuery.data.totalChallenges) * 100, - ) + (summaryQuery.data.solved / summaryQuery.data.totalChallenges) * 100, + ) : 0; const MotionBlock = motion.div; @@ -105,25 +105,25 @@ const Dashboard = () => { /> {/* Featured Hero */} -
Recommended for you -

Mastering Dynamic
Programming

+

Mastering Dynamic
Programming

Push your limits with this week's elite challenge. Solve complex optimizations and climb the global leaderboards.

- -
- - +500 Bonus XP -
+ +
+ + +500 Bonus XP +
- +
@@ -183,10 +183,9 @@ const Dashboard = () => {
- + }`}> {challenge.difficulty} {challenge.points} XP @@ -203,7 +202,7 @@ const Dashboard = () => { ))}
)} - +
Explore More Missions @@ -225,11 +224,10 @@ const Dashboard = () => {

{submission.challengeId?.title || 'Unknown Challenge'}

{new Date(submission.submittedAt).toLocaleDateString()}

-

+ 'bg-yellow-500/20 text-yellow-500' + }`}> {submission.status}

@@ -257,16 +255,15 @@ const Dashboard = () => { View All
- +
{pendingTasksPreview.map((task) => (
navigate(`/challenge/${task.id}`)} className="group macos-glass p-5 hover:border-accent transition-all cursor-pointer bg-white/[0.02]">
{task.category} - + {task.priority}
diff --git a/client/src/pages/Leaderboard.jsx b/client/src/pages/Leaderboard.jsx index 9841aa8..b7aa52f 100644 --- a/client/src/pages/Leaderboard.jsx +++ b/client/src/pages/Leaderboard.jsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; -import { FiAward, FiSearch, FiUsers, FiTrendingUp, FiZap } from 'react-icons/fi'; +import { FiAward, FiSearch, FiUsers, FiTrendingUp, FiZap, FiChevronUp, FiChevronDown } from 'react-icons/fi'; import { motion, AnimatePresence } from 'framer-motion'; import Card from '../components/Card'; import EmptyState from '../components/EmptyState'; @@ -104,6 +104,42 @@ const Leaderboard = () => { const [filters, setFilters] = useState({ window: 'all', page: 1, limit: 20 }); const [search, setSearch] = useState(''); const [leaderType, setLeaderType] = useState('individual'); // 'individual' or 'clans' + const [sortConfig, setSortConfig] = useState(null); + + const requestSort = (key) => { + let direction = 'asc'; + if (sortConfig && sortConfig.key === key) { + if (sortConfig.direction === 'asc') { + direction = 'desc'; + } else { + setSortConfig(null); + return; + } + } else { + if (key === 'totalPoints' || key === 'solvedCount' || (key === 'clanOrMembers' && leaderType === 'clans')) { + direction = 'desc'; + } + } + setSortConfig({ key, direction }); + }; + + const renderSortableHeader = (label, sortKey, align = 'left') => ( + requestSort(sortKey)} + > +
+ {label} + {sortConfig?.key === sortKey ? ( + sortConfig.direction === 'asc' ? : + ) : ( +
+ +
+ )} +
+ + ); const leaderboardQuery = useQuery({ queryKey: ['leaderboard', filters, leaderType], @@ -147,10 +183,42 @@ const Leaderboard = () => { const meta = leaderType === 'clans' ? { page: 1, totalPages: 1 } : (leaderboardQuery.data?.meta || {}); const visibleRows = useMemo(() => { + let result = [...rows]; + const query = search.trim().toLowerCase(); - if (!query) return rows; - return rows.filter((row) => (row.username || row.name).toLowerCase().includes(query)); - }, [rows, search]); + if (query) { + result = result.filter((row) => (row.username || row.name).toLowerCase().includes(query)); + } + + if (sortConfig) { + result.sort((a, b) => { + let valA = a[sortConfig.key]; + let valB = b[sortConfig.key]; + + if (sortConfig.key === 'nameOrUsername') { + valA = a.username || a.name || ''; + valB = b.username || b.name || ''; + } + if (sortConfig.key === 'clanOrMembers') { + valA = leaderType === 'individual' ? (a.clan || '') : (a.memberCount || 0); + valB = leaderType === 'individual' ? (b.clan || '') : (b.memberCount || 0); + } + + if (typeof valA === 'string') valA = valA.toLowerCase(); + if (typeof valB === 'string') valB = valB.toLowerCase(); + + if (valA < valB) { + return sortConfig.direction === 'asc' ? -1 : 1; + } + if (valA > valB) { + return sortConfig.direction === 'asc' ? 1 : -1; + } + return 0; + }); + } + + return result; + }, [rows, search, sortConfig, leaderType]); const myRow = leaderType === 'individual' ? rows.find((row) => row.username === user?.username) : null; const topThree = rows.slice(0, 3); @@ -164,14 +232,14 @@ const Leaderboard = () => {