diff --git a/js/src/app/embed/leaderboard/LeaderboardEmbed.tsx b/js/src/app/embed/leaderboard/LeaderboardEmbed.tsx
index 7c69bbb40..924bef8b4 100644
--- a/js/src/app/embed/leaderboard/LeaderboardEmbed.tsx
+++ b/js/src/app/embed/leaderboard/LeaderboardEmbed.tsx
@@ -1,4 +1,4 @@
-import OrgEmbedView from "@/app/embed/leaderboard/_components/OrgEmbedView";
+import { CurrentLeaderboard } from "@/app/leaderboard/_components/Leaderboard";
import { Box } from "@mantine/core";
export default function LeaderboardEmbed() {
@@ -6,7 +6,7 @@ export default function LeaderboardEmbed() {
<>
-
+
>
diff --git a/js/src/app/embed/leaderboard/_components/OrgEmbedView.tsx b/js/src/app/embed/leaderboard/_components/OrgEmbedView.tsx
deleted file mode 100644
index 9b88e3963..000000000
--- a/js/src/app/embed/leaderboard/_components/OrgEmbedView.tsx
+++ /dev/null
@@ -1,246 +0,0 @@
-import OrgHeader from "@/app/embed/leaderboard/_components/OrgHeader";
-import LeaderboardSkeleton from "@/app/leaderboard/_components/LeaderboardSkeleton";
-import LeaderboardCard from "@/components/ui/LeaderboardCard";
-import CustomPagination from "@/components/ui/table/CustomPagination";
-import SearchBox from "@/components/ui/table/SearchBox";
-import Toast from "@/components/ui/toast/Toast";
-import { useCurrentLeaderboardUsersQuery } from "@/lib/api/queries/leaderboard";
-import getOrdinal from "@/lib/helper/ordinal";
-import { theme } from "@/lib/theme";
-import {
- Box,
- Button,
- Center,
- Flex,
- Overlay,
- Table,
- Tooltip,
-} from "@mantine/core";
-import { IconCircleCheckFilled } from "@tabler/icons-react";
-import { useEffect, useMemo } from "react";
-import { FaArrowLeft, FaArrowRight, FaDiscord } from "react-icons/fa";
-import { SiLeetcode } from "react-icons/si";
-import { Link, useSearchParams } from "react-router-dom";
-
-export default function OrgLeaderboardEmbed() {
- const [searchParams] = useSearchParams();
-
- const pageSizeParam = searchParams.get("pageSize");
- const pageSize = pageSizeParam ? Number(pageSizeParam) : undefined;
-
- const {
- status,
- isPlaceholderData,
- data,
- page,
- goTo,
- goBack,
- goForward,
- setSearchQuery,
- searchQuery,
- debouncedQuery,
- filters,
- onFilterReset,
- } = useCurrentLeaderboardUsersQuery({ pageSize });
-
- const activeFilter = useMemo(() => {
- const active = Object.typedEntries(filters).filter(
- ([, enabled]) => enabled,
- );
-
- return active.length === 1 ? active[0][0] : undefined;
- }, [filters]);
-
- useEffect(() => {
- const activeCount = Object.typedEntries(filters).filter(
- ([, enabled]) => enabled,
- ).length;
-
- if (activeCount > 1) {
- onFilterReset();
- }
- }, [filters, onFilterReset]);
-
- if (status === "pending") {
- return ;
- }
-
- if (status === "error") {
- return ;
- }
-
- if (!data.success) {
- return
Sorry, there are no users to display.
;
- }
-
- const pageData = data.payload;
- const [first, second, third] = pageData.items;
-
- return (
- <>
-
-
-
-
-
- {page === 1 && second && !debouncedQuery && (
-
-
-
- )}
- {page === 1 && first && !debouncedQuery && (
-
- )}
- {page === 1 && third && !debouncedQuery && (
-
- )}
-
- {
- setSearchQuery(event.currentTarget.value);
- }}
- placeholder={"Search for User"}
- smallPadding
- />
-
-
- {isPlaceholderData && (
-
- )}
-
-
- #
- Name
- Pts
-
-
-
- {pageData.items.map(({ index: rank, ...entry }, index) => {
- if (page === 1 && !debouncedQuery && [0, 1, 2].includes(index))
- return null;
- return (
-
- {rank}
-
-
- {entry.nickname ?
-
-
- {" "}
- {entry.nickname}
-
-
- :
- {" "}
- {entry.discordName}
-
- }
-
- {" "}
- {entry.leetcodeUsername}
-
-
-
- {entry.totalScore}
-
- );
- })}
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/js/src/app/leaderboard/_components/Leaderboard.tsx b/js/src/app/leaderboard/_components/Leaderboard.tsx
index dc07339aa..6205a2c6b 100644
--- a/js/src/app/leaderboard/_components/Leaderboard.tsx
+++ b/js/src/app/leaderboard/_components/Leaderboard.tsx
@@ -1,3 +1,4 @@
+import OrgHeader from "@/app/embed/leaderboard/_components/OrgHeader";
import LeaderboardSkeleton from "@/app/leaderboard/_components/LeaderboardSkeleton";
import FilterDropdown from "@/components/ui/dropdown/FilterDropdown";
import FilterDropdownItem from "@/components/ui/dropdown/FilterDropdownItem";
@@ -34,12 +35,25 @@ import {
Tooltip,
} from "@mantine/core";
import { IconCircleCheckFilled } from "@tabler/icons-react";
+import { useEffect, useMemo } from "react";
import { FaArrowLeft, FaArrowRight, FaDiscord } from "react-icons/fa";
import { SiLeetcode } from "react-icons/si";
import { Link } from "react-router-dom";
-export function CurrentLeaderboard() {
- const query = useCurrentLeaderboardUsersQuery();
+type LeaderboardOptions = {
+ embedded?: boolean;
+};
+
+function getPageSizeFromParams(): number | undefined {
+ const searchParams = new URLSearchParams(window.location.search);
+ const pageSizeParam = searchParams.get("pageSize");
+ return pageSizeParam ? Number(pageSizeParam) : undefined;
+}
+
+export function CurrentLeaderboard(props: LeaderboardOptions = {}) {
+ const query = useCurrentLeaderboardUsersQuery(
+ props.embedded ? { pageSize: getPageSizeFromParams() } : {},
+ );
const metadataQuery = useCurrentLeaderboardMetadataQuery();
const dateRange =
@@ -52,11 +66,15 @@ export function CurrentLeaderboard() {
query={query}
startDate={dateRange?.startDate}
endDate={dateRange?.endDate}
+ {...props}
/>
);
}
-export function LeaderboardById({ leaderboardId }: { leaderboardId: string }) {
+export function LeaderboardById({
+ leaderboardId,
+ ...props
+}: LeaderboardOptions & { leaderboardId: string }) {
const query = useLeaderboardUsersByIdQuery({ leaderboardId });
const metadataQuery = useLeaderboardMetadataByIdQuery(leaderboardId);
@@ -70,6 +88,7 @@ export function LeaderboardById({ leaderboardId }: { leaderboardId: string }) {
query={query}
startDate={dateRange?.startDate}
endDate={dateRange?.endDate}
+ {...props}
/>
);
}
@@ -78,7 +97,8 @@ function LeaderboardIndex({
query,
startDate,
endDate,
-}: {
+ embedded = false,
+}: LeaderboardOptions & {
query: ReturnType;
startDate?: string;
endDate?: string;
@@ -102,6 +122,23 @@ function LeaderboardIndex({
onFilterReset,
} = query;
+ const activeFilter = useMemo(() => {
+ const entries = filters ? Object.typedEntries(filters) : [];
+ const active = entries.filter(([, enabled]) => enabled);
+ return active.length === 1 ? active[0][0] : undefined;
+ }, [filters]);
+
+ useEffect(() => {
+ if (embedded) {
+ const activeCount = Object.typedEntries(filters).filter(
+ ([, enabled]) => enabled,
+ ).length;
+ if (activeCount > 1) {
+ onFilterReset();
+ }
+ }
+ }, [embedded, filters, onFilterReset]);
+
if (status === "pending") {
return ;
}
@@ -116,8 +153,9 @@ function LeaderboardIndex({
const pageData = data.payload;
const [first, second, third] = pageData.items;
+ const shouldShowTopThree = page === 1 && !debouncedQuery;
const cardItems = pageData.items.filter((_, index) => {
- if (page === 1 && !debouncedQuery && [0, 1, 2].includes(index)) {
+ if (shouldShowTopThree && [0, 1, 2].includes(index)) {
return false;
}
return true;
@@ -127,6 +165,19 @@ function LeaderboardIndex({
return (
<>
+ {embedded && }
+ {embedded && (
+
+
+
+ )}
- {page === 1 && second && !debouncedQuery && (
+ {shouldShowTopThree && second && (
)}
- {page === 1 && first && !debouncedQuery && (
+ {shouldShowTopThree && first && (
)}
- {page === 1 && third && !debouncedQuery && (
+ {shouldShowTopThree && third && (
)}
-
-
- {schoolFF &&
- ApiUtils.getAllSupportedTagEnums().map((tagEnum) => (
- {
- const metadata = ApiUtils.getMetadataByTagEnum(tagEnum);
-
- return (
-
- {metadata.shortName}
-
-
- );
- }}
- value={filters[tagEnum]}
- toggle={() => toggleFilter(tagEnum)}
- />
- ))}
-
- Toggle Global Rank
-
- }
- />
-
-
-
+ {schoolFF &&
+ ApiUtils.getAllSupportedTagEnums().map((tagEnum) => (
+ {
+ const metadata = ApiUtils.getMetadataByTagEnum(tagEnum);
+ return (
+
+ {metadata.shortName}
+
+
+ );
+ }}
+ value={filters[tagEnum]}
+ toggle={() => toggleFilter(tagEnum)}
+ />
+ ))}
+
+ Toggle Global Rank
+
+ }
+ />
+
+
+
+ )}
{