diff --git a/frontend/__tests__/components/common/AsyncContent.spec.tsx b/frontend/__tests__/components/common/AsyncContent.spec.tsx index da25c43ee814..ae68c1156ff4 100644 --- a/frontend/__tests__/components/common/AsyncContent.spec.tsx +++ b/frontend/__tests__/components/common/AsyncContent.spec.tsx @@ -47,11 +47,13 @@ describe("AsyncContent", () => { }); it("renders on resolve", async () => { - renderWithQuery({ result: "Test Data" }); + const { container } = renderWithQuery({ result: "Test Data" }); await waitFor(() => { expect(screen.getByTestId("content")).toHaveTextContent("Test Data"); }); + const preloader = container.querySelector(".preloader"); + expect(preloader).not.toBeInTheDocument(); }); it("renders default error message on fail", async () => { @@ -205,7 +207,10 @@ describe("AsyncContent", () => { }); it("renders on resolve", async () => { - renderWithQuery({ first: "First Data", second: "Second Data" }); + const { container } = renderWithQuery({ + first: "First Data", + second: "Second Data", + }); await waitFor(() => { expect(screen.getByTestId("first")).toHaveTextContent("First Data"); @@ -213,6 +218,8 @@ describe("AsyncContent", () => { await waitFor(() => { expect(screen.getByTestId("second")).toHaveTextContent("Second Data"); }); + const preloader = container.querySelector(".preloader"); + expect(preloader).not.toBeInTheDocument(); }); it("renders default error message on fail", async () => { diff --git a/frontend/__tests__/components/ui/table/DataTable.spec.tsx b/frontend/__tests__/components/ui/table/DataTable.spec.tsx index 5b4143708140..17102d8cf5c4 100644 --- a/frontend/__tests__/components/ui/table/DataTable.spec.tsx +++ b/frontend/__tests__/components/ui/table/DataTable.spec.tsx @@ -30,12 +30,14 @@ type Person = { const columns = [ { + id: "name", accessorKey: "name", header: "Name", cell: (info: any) => info.getValue(), - meta: { breakpoint: "xxs" }, + meta: { maxBreakpoint: "sm" }, }, { + id: "age", accessorKey: "age", header: "Age", cell: (info: any) => info.getValue(), @@ -144,8 +146,13 @@ describe("DataTable", () => { }); render(() => ); - - expect(screen.getByText("Name")).toBeInTheDocument(); - expect(screen.queryByText("Age")).not.toBeInTheDocument(); + const nameHeader = screen.getByRole("button", { + name: "Name", + }).parentElement; + const ageHeader = screen.getByRole("button", { name: "Age" }).parentElement; + + expect(nameHeader).not.toHaveClass("hidden"); + expect(nameHeader).toHaveClass("sm:hidden"); + expect(ageHeader).toHaveClass("hidden sm:table-cell"); }); }); diff --git a/frontend/src/html/pages/leaderboards.html b/frontend/src/html/pages/leaderboards.html deleted file mode 100644 index 4bb34916f4b4..000000000000 --- a/frontend/src/html/pages/leaderboards.html +++ /dev/null @@ -1,262 +0,0 @@ - diff --git a/frontend/src/index.html b/frontend/src/index.html index 8073ca189c58..c219cac26916 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -58,7 +58,9 @@ - +
.divider { - height: 0.25rem; - width: 100%; - background: var(--sub-alt-color); - border-radius: calc(var(--roundness) / 2); - margin-bottom: 1em; - } - - .titleAndButtons { - align-items: center; - font-size: 1em; - display: grid; - grid-template-columns: 1fr 1fr; - justify-content: space-between; - button { - width: 3em; - } - .title { - font-size: 1rem; - color: var(--sub-color); - } - .jumpButtons { - justify-self: end; - display: grid; - grid-auto-flow: column; - gap: 0.5em; - align-items: center; - .updating { - font-size: 1.5em; - color: var(--sub-color); - margin-left: 0.5em; - } - } - } - - & > .title { - font-size: 1.25rem; - color: var(--sub-color); - } - - .narrow { - display: none; - } - - .bigUser { - // color: var(--main-color); - font-size: 1em; - margin-bottom: 2em; - margin-top: 2em; - background: var(--sub-alt-color); - padding: 1em 2em; - border-radius: var(--roundness); - display: flex; - align-items: center; - gap: 2em; - // .rank { - // width: 7ch; - // text-align: left; - // } - - .warning { - padding: 0.5em 0; - text-align: center; - grid-column: 1 / -1; - color: var(--sub-color); - width: 100%; - } - - .userInfo { - flex-grow: 1; - } - - .stat { - text-align: right; - .title { - font-size: 0.75em; - color: var(--sub-color); - } - .sub { - opacity: 0.5; - } - &:last-child { - text-wrap-mode: nowrap; - } - } - .date { - font-size: 0.75em; - // color: var(--sub-color); - .sub { - font-size: 0.75em; - color: var(--sub-color); - } - } - &.you { - .userInfo { - .bottom { - font-size: 0.75em; - color: var(--sub-color); - } - } - // font-size: 1rem; - // .stat .title { - // font-size: 0.8em; - // } - } - } - table { - width: 100%; - border-spacing: 0; - border-collapse: collapse; - - --padding: 1em 1.5rem; - - .sub { - opacity: 0.5; - } - - td { - padding: var(--padding); - } - - .globalRank { - i { - display: none; - } - span { - display: inline; - } - } - &.friendsOnly { - td:first-child { - display: table-cell; - } - .globalRank { - i { - display: inline; - } - span { - display: none; - } - } - } - td:first-child { - display: none; - } - td:first-child, - td:nth-child(2) { - // padding: 0; - width: 0; - text-align: center; - } - - thead { - color: var(--sub-color); - font-size: 0.75em; - - td { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 99; - &.stat { - width: 15ch; - text-align: right; - } - &.date { - width: 1px; - text-align: right; - } - } - } - - .avatarNameBadge { - display: grid; - grid-template-columns: max-content max-content auto; - gap: 0.5em; - place-items: center left; - .avatar .userIcon { - color: var(--sub-color); - } - .entryName { - text-decoration: none; - color: var(--text-color); - cursor: pointer; - } - .avatar { - --size: 1.125em; - grid-row: 1/2; - grid-column: 1/2; - } - .badge { - font-size: 0.75em; - } - .flagsAndBadge { - display: flex; - gap: 0.5em; - color: var(--sub-color); - place-items: center; - } - } - - tbody { - color: var(--text-color); - - tr.me { - color: var(--main-color); - a { - color: var(--main-color) !important; - } - } - - td.stat { - text-align: right; - } - - td.date { - text-wrap-mode: nowrap; - text-align: right; - font-size: 0.75em; - } - - tr:nth-child(odd) td { - background: var(--sub-alt-color); - } - td:nth-child(1) { - border-radius: calc(var(--roundness) / 2) 0 0 - calc(var(--roundness) / 2); - } - td:last-child { - border-radius: 0 calc(var(--roundness) / 2) - calc(var(--roundness) / 2) 0; - } - } - } - & > .loading { - display: grid; - place-items: center; - font-size: 3em; - color: var(--sub-color); - padding: 1em; - } - } - .error { - display: grid; - grid-auto-flow: column; - gap: 2rem; - place-content: center; - align-items: center; - font-size: 2em; - color: var(--sub-color); - padding: 1em; - } - .sideButtons { - align-content: start; - align-items: start; - grid-area: buttons; - display: grid; - gap: 1em; - align-content: start; - background: var(--sub-alt-color); - height: max-content; - border-radius: var(--roundness); - padding: 1rem; - button { - justify-content: start; - padding-left: 0.75em; - } - .divider { - background: var(--bg-color); - width: 100%; - height: 0.25em; - border-radius: var(--roundness); - } - .buttonGroup { - display: grid; - gap: 1em; - } - } - } -} diff --git a/frontend/src/styles/media-queries-brown.scss b/frontend/src/styles/media-queries-brown.scss index 0dec474c9c7a..021262ed0069 100644 --- a/frontend/src/styles/media-queries-brown.scss +++ b/frontend/src/styles/media-queries-brown.scss @@ -53,50 +53,6 @@ .testActivity { display: none; } - - .pageLeaderboards { - .content .tableAndUser { - //font-size: 0.7rem; - .bigUser { - gap: 1em; - padding-left: 0.75em; - .stat.narrow:last-child { - font-size: 0.75em; - } - .userInfo { - font-size: 0.8em; - } - .rank { - margin-right: 0.5em; - } - } - .titleAndButtons { - // grid-template-columns: 1fr; - .title { - // text-align: center; - font-size: 1em; - } - } - table { - .avatarNameBadge .flagsAndBadge .badge .text { - display: block; - } - tbody td.date { - font-size: 0.75em; - } - .avatarNameBadge { - grid-template-columns: 1.25em 1fr; - grid-template-areas: - "avatar name" - "badges badges"; - .flagsAndBadge { - grid-area: badges; - // justify-self: center; - } - } - } - } - } .pageFriends { .content .friends table { td:nth-child(3) { diff --git a/frontend/src/styles/media-queries-gray.scss b/frontend/src/styles/media-queries-gray.scss index 4cdd96e29510..bf120d5cece2 100644 --- a/frontend/src/styles/media-queries-gray.scss +++ b/frontend/src/styles/media-queries-gray.scss @@ -2,18 +2,6 @@ @use "./media.scss" as *; @include media-query(gray) { - .pageLeaderboards .content .tableAndUser { - .titleAndButtons { - grid-template-columns: 1fr; - gap: 0.5em; - .title { - text-align: right; - } - } - .rawAndConsistency { - display: none; - } - } header { gap: 0.25rem; nav .textButton { diff --git a/frontend/src/styles/media-queries-green.scss b/frontend/src/styles/media-queries-green.scss index 68e886cf336e..ea912af5134e 100644 --- a/frontend/src/styles/media-queries-green.scss +++ b/frontend/src/styles/media-queries-green.scss @@ -150,24 +150,7 @@ // border-radius: 0.2em; // } } - .pageLeaderboards { - .content { - align-content: start; - grid-template-columns: 1fr; - grid-template-areas: "buttons" "table"; - .buttons { - // grid-template-columns: 1fr 1fr; - font-size: 0.9em; - .buttonGroup { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); - button { - justify-content: center; - } - } - } - } - } + .pageFriends { .content .friends table { td:nth-child(4), diff --git a/frontend/src/styles/media-queries-orange.scss b/frontend/src/styles/media-queries-orange.scss index c31e32a38377..263fe50963c4 100644 --- a/frontend/src/styles/media-queries-orange.scss +++ b/frontend/src/styles/media-queries-orange.scss @@ -15,9 +15,4 @@ // width: 1.6em; // } } - .pageLeaderboards { - .content { - grid-template-columns: 15rem 1fr; - } - } } diff --git a/frontend/src/styles/media-queries-purple.scss b/frontend/src/styles/media-queries-purple.scss index 3020530eade0..e8a0c12304d8 100644 --- a/frontend/src/styles/media-queries-purple.scss +++ b/frontend/src/styles/media-queries-purple.scss @@ -12,33 +12,6 @@ display: grid; } - .pageLeaderboards { - .content .bigtitle .text:after { - left: 0.1rem; - transform: none; - } - .content .tableAndUser { - font-size: clamp(0.7rem, 2.8vw, 0.9rem); - .bigUser { - gap: 1.5em; - } - table { - td { - padding: 0.5em; - } - .avatarNameBadge .flagsAndBadge .badge .text { - display: none; - } - tbody td:nth-child(2) { - width: 100%; - } - } - .bigUser { - padding: 0.5em; - padding-left: 1em; - } - } - } header { nav { font-size: 0.9rem; diff --git a/frontend/src/styles/media-queries-yellow.scss b/frontend/src/styles/media-queries-yellow.scss index 6f6c9b77d1a0..5d7e27a6c25a 100644 --- a/frontend/src/styles/media-queries-yellow.scss +++ b/frontend/src/styles/media-queries-yellow.scss @@ -62,31 +62,7 @@ display: none; } } - .pageLeaderboards { - .content .tableAndUser { - font-size: 0.9rem; - .bigUser { - grid-template-columns: auto 1fr auto auto auto; - } - .narrow { - display: table-cell; - } - .wide { - display: none; - } - table tbody { - td.date { - font-size: 1em; - } - } - table td { - padding: 1em; - } - .bigUser { - padding: 1em; - } - } - } + .pageFriends { .content .friends table, .content .pendingRequests table { diff --git a/frontend/src/styles/media.scss b/frontend/src/styles/media.scss index feaabb0e953a..c08e7fa41dd7 100644 --- a/frontend/src/styles/media.scss +++ b/frontend/src/styles/media.scss @@ -3,7 +3,7 @@ $breakpoints: ( yellow: calc(1280px + 5rem), green: calc(1024px + 5rem), blue: calc(768px + 5rem), - purple: calc(641px + 5rem), + purple: calc(640px + 5rem), brown: 425px, gray: 330px, ); diff --git a/frontend/src/ts/components/common/AsyncContent.tsx b/frontend/src/ts/components/common/AsyncContent.tsx index 239a581b4911..cea43ab83615 100644 --- a/frontend/src/ts/components/common/AsyncContent.tsx +++ b/frontend/src/ts/components/common/AsyncContent.tsx @@ -29,6 +29,7 @@ type BaseProps = { errorMessage?: string; ignoreError?: true; loader?: JSXElement; + errorClass?: string; }; type QueryProps = { @@ -115,7 +116,9 @@ export default function AsyncContent( props.loader ?? ; const errorText = (err: unknown): JSXElement | undefined => - props.ignoreError ? undefined :
{handleError(err)}
; + props.ignoreError ? undefined : ( +
{handleError(err)}
+ ); return ( diff --git a/frontend/src/ts/components/common/DiscordAvatar.tsx b/frontend/src/ts/components/common/DiscordAvatar.tsx index 3edd40c926a6..1f331125f0b7 100644 --- a/frontend/src/ts/components/common/DiscordAvatar.tsx +++ b/frontend/src/ts/components/common/DiscordAvatar.tsx @@ -32,8 +32,9 @@ export function DiscordAvatar(props: { <> +
} else={
diff --git a/frontend/src/ts/components/common/User.tsx b/frontend/src/ts/components/common/User.tsx index 3b8598b05a62..d48a3a9c19fc 100644 --- a/frontend/src/ts/components/common/User.tsx +++ b/frontend/src/ts/components/common/User.tsx @@ -5,6 +5,7 @@ import { SupportsFlags, UserFlagOptions, } from "../../controllers/user-flag-controller"; +import { cn } from "../../utils/cn"; import { Button } from "./Button"; import { DiscordAvatar } from "./DiscordAvatar"; import { UserBadge } from "./UserBadge"; @@ -12,6 +13,7 @@ import { UserFlags } from "./UserFlags"; export function User( props: { + class?: string; user: SupportsFlags & Pick & { badgeId?: number; @@ -20,7 +22,9 @@ export function User( } & UserFlagOptions, ): JSXElement { return ( -
+
- +
); diff --git a/frontend/src/ts/components/common/UserBadge.tsx b/frontend/src/ts/components/common/UserBadge.tsx index 78996cdd0431..c69921d249df 100644 --- a/frontend/src/ts/components/common/UserBadge.tsx +++ b/frontend/src/ts/components/common/UserBadge.tsx @@ -4,15 +4,20 @@ import { badges, UserBadge as UserBadgeType, } from "../../controllers/badge-controller"; +import { cn } from "../../utils/cn"; import { Fa } from "./Fa"; -export function UserBadge(props: { id?: number; iconOnly?: true }): JSXElement { +export function UserBadge(props: { + id?: number; + iconOnly?: true; + class?: string; +}): JSXElement { const badge = (): UserBadgeType | undefined => props.id !== undefined ? badges[props.id] : undefined; return (
- +
diff --git a/frontend/src/ts/components/mount.tsx b/frontend/src/ts/components/mount.tsx index fd8149609be9..0c76502178b1 100644 --- a/frontend/src/ts/components/mount.tsx +++ b/frontend/src/ts/components/mount.tsx @@ -11,12 +11,14 @@ import { Overlays } from "./layout/overlays/Overlays"; import { Modals } from "./modals/Modals"; import { AboutPage } from "./pages/AboutPage"; import { MyProfile } from "./pages/account/MyProfile"; +import { LeaderboardPage } from "./pages/leaderboard/LeaderboardPage"; import { ProfilePage } from "./pages/profile/ProfilePage"; import { ProfileSearchPage } from "./pages/profile/ProfileSearchPage"; const components: Record JSXElement> = { footer: () =>