Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 61 additions & 25 deletions components/LeetCodeDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Check, X, ChevronLeft, ChevronRight } from "lucide-react";
import { Check, X, ChevronLeft, ChevronRight, ChevronDown, ChevronUp } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
Expand Down Expand Up @@ -75,14 +75,15 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({

const [isClient, setIsClient] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const [difficultyFilter, setDifficultyFilter] = useState("all");
const [difficultyFilter, setDifficultyFilter] = useState<string[]>([]);
const [selectedCompany] = useState("");
const [checkedItems, setCheckedItems] = useState<{ [key: string]: boolean }>({});
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(10);
const [goToPage, setGoToPage] = useState("");
const [selectedTopics, setSelectedTopics] = useState<string[]>([]);
const [sortDirection, setSortDirection] = useState<"asc" | "desc" | null>(null);
const [frequencySort, setFrequencySort] = useState<"asc" | "desc" | null>(null);
const [acceptanceSort, setAcceptanceSort] = useState<"asc" | "desc" | null>(null);
const [timeframeFilter, setTimeframeFilter] = useState("all");
const [progressLoading, setProgressLoading] = useState(false);
const { userId } = useAuth();
Expand Down Expand Up @@ -236,7 +237,7 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({
.some((topic) => topic.trim().includes(word))
);
const matchesDifficulty =
difficultyFilter === "all" || question.Difficulty === difficultyFilter;
difficultyFilter.length === 0 || difficultyFilter.includes(question.Difficulty);
const matchesCompany = !selectedCompany || question.company === selectedCompany;
const matchesTopic =
selectedTopics.length === 0 ||
Expand All @@ -254,21 +255,41 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({
}, [questions, searchQuery, difficultyFilter, selectedCompany, selectedTopics, timeframeFilter]);

const filteredAndSortedQuestions = useMemo(() => {
let result = filteredQuestions;
let result = [...filteredQuestions];

if (sortDirection) {
result = [...result].sort((a, b) => {
result.sort((a, b) => {
// First sort by frequency if it's set
if (frequencySort) {
const freqA = parseFloat(a["Frequency %"]);
const freqB = parseFloat(b["Frequency %"]);
return sortDirection === "asc" ? freqA - freqB : freqB - freqA;
});
}
const freqResult = frequencySort === "asc" ? freqA - freqB : freqB - freqA;
if (freqResult !== 0) return freqResult;
}

// Then sort by acceptance if it's set
if (acceptanceSort) {
const accA = parseFloat(a["Acceptance %"]);
const accB = parseFloat(b["Acceptance %"]);
const accResult = acceptanceSort === "asc" ? accA - accB : accB - accA;
if (accResult !== 0) return accResult;
}

return 0;
});

return result;
}, [filteredQuestions, sortDirection]);
}, [filteredQuestions, frequencySort, acceptanceSort]);

const handleFrequencySort = () => {
setSortDirection((prev) => {
setFrequencySort((prev) => {
if (prev === null) return "desc";
if (prev === "desc") return "asc";
return null;
});
};

const handleAcceptanceSort = () => {
setAcceptanceSort((prev) => {
if (prev === null) return "desc";
if (prev === "desc") return "asc";
return null;
Expand Down Expand Up @@ -471,17 +492,12 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({
/>
</div>

<Select value={difficultyFilter} onValueChange={setDifficultyFilter}>
<SelectTrigger className="w-full md:w-52">
<SelectValue placeholder="Difficulty" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All Difficulties</SelectItem>
<SelectItem value="Easy">Easy</SelectItem>
<SelectItem value="Medium">Medium</SelectItem>
<SelectItem value="Hard">Hard</SelectItem>
</SelectContent>
</Select>
<TopicDropdown
options={["Easy", "Medium", "Hard"]}
selectedOptions={difficultyFilter}
setSelectedOptions={setDifficultyFilter}
placeholder="Difficulty"
/>

<Select value={timeframeFilter} onValueChange={setTimeframeFilter}>
<SelectTrigger className="w-full md:w-56">
Expand All @@ -500,6 +516,7 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({
options={uniqueTopics}
selectedOptions={selectedTopics}
setSelectedOptions={setSelectedTopics}
placeholder="Topics"
/>
</div>

Expand All @@ -518,12 +535,31 @@ const LeetCodeDashboard: React.FC<LeetCodeDashboardProps> = ({
<TableHead>Company</TableHead>
<TableHead>Difficulty</TableHead>
<TableHead>Topics</TableHead>
<TableHead className="text-right">Acceptance</TableHead>
<TableHead
className="text-right cursor-pointer hover:text-primary transition-colors"
onClick={handleAcceptanceSort}
>
<div className="flex items-center justify-end gap-1">
Acceptance
{acceptanceSort === "desc" && <ChevronDown className="h-4 w-4" />}
{acceptanceSort === "asc" && <ChevronUp className="h-4 w-4" />}
{acceptanceSort === null && (
<ChevronDown className="h-4 w-4 opacity-30" />
)}
</div>
</TableHead>
<TableHead
className="text-right cursor-pointer hover:text-primary transition-colors"
onClick={handleFrequencySort}
>
Frequency
<div className="flex items-center justify-end gap-1">
Frequency
{frequencySort === "desc" && <ChevronDown className="h-4 w-4" />}
{frequencySort === "asc" && <ChevronUp className="h-4 w-4" />}
{frequencySort === null && (
<ChevronDown className="h-4 w-4 opacity-30" />
)}
</div>
</TableHead>
<TableHead className="text-center">Premium</TableHead>
<TableHead className="text-left">Solution</TableHead>
Expand Down
6 changes: 3 additions & 3 deletions components/TopicDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ interface TopicDropdownProps {
options: string[];
selectedOptions: string[];
setSelectedOptions: (options: string[]) => void;
placeholder?: string;
}

export default function TopicDropdown({
options,
selectedOptions,
setSelectedOptions,
placeholder,
}: TopicDropdownProps) {
const [open, setOpen] = React.useState(false);

Expand All @@ -46,9 +48,7 @@ export default function TopicDropdown({
className="justify-between min-w-[200px] bg-transparent [&>span]:line-clamp-1"
>
<span className="line-clamp-1">
{selectedOptions.length === 0
? "Select topics..."
: `${selectedOptions.length} selected`}
{selectedOptions.length === 0 ? placeholder : `${selectedOptions.length} selected`}
</span>
<ChevronDown className="h-4 w-4 opacity-50" />
</Button>
Expand Down