This commit is contained in:
parent
39026d9a32
commit
e60a14e799
@ -1,4 +1,5 @@
|
|||||||
import { PreloadResources } from "@/components/preload-resources";
|
import { PreloadResources } from "@/components/preload-resources";
|
||||||
|
import { AnimatePresence } from "framer-motion";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import localFont from "next/font/local";
|
import localFont from "next/font/local";
|
||||||
import BackgroundImage from "../components/background-image";
|
import BackgroundImage from "../components/background-image";
|
||||||
@ -67,10 +68,12 @@ export default function RootLayout({
|
|||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange>
|
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange>
|
||||||
<QueryProvider>
|
<QueryProvider>
|
||||||
<main className="z-[9999] m-auto flex h-screen flex-col items-center md:max-w-[1200px]">
|
<AnimatePresence>
|
||||||
<NavBar />
|
<main className="z-[9999] m-auto flex h-screen flex-col items-center md:max-w-[1200px]">
|
||||||
{children}
|
<NavBar />
|
||||||
</main>
|
{children}
|
||||||
|
</main>
|
||||||
|
</AnimatePresence>
|
||||||
</QueryProvider>
|
</QueryProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
@ -47,7 +47,7 @@ export default function LeaderboardScores({ leaderboard }: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }}>
|
<motion.div initial={{ opacity: 0, y: -50 }} exit={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }}>
|
||||||
<Card className="flex gap-2">
|
<Card className="flex gap-2">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
{isError && <p>Oopsies! Something went wrong.</p>}
|
{isError && <p>Oopsies! Something went wrong.</p>}
|
||||||
|
@ -8,7 +8,7 @@ import { capitalizeFirstLetter } from "@/common/string-utils";
|
|||||||
import useWindowDimensions from "@/hooks/use-window-dimensions";
|
import useWindowDimensions from "@/hooks/use-window-dimensions";
|
||||||
import { ClockIcon, TrophyIcon } from "@heroicons/react/24/solid";
|
import { ClockIcon, TrophyIcon } from "@heroicons/react/24/solid";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { motion, useAnimation } from "framer-motion";
|
import { motion, useAnimation, Variants } from "framer-motion";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import Card from "../card";
|
import Card from "../card";
|
||||||
import Pagination from "../input/pagination";
|
import Pagination from "../input/pagination";
|
||||||
@ -35,11 +35,48 @@ type Props = {
|
|||||||
page: number;
|
page: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const containerVariants: Variants = {
|
||||||
|
hiddenRight: {
|
||||||
|
opacity: 0,
|
||||||
|
x: 50,
|
||||||
|
},
|
||||||
|
hiddenLeft: {
|
||||||
|
opacity: 0,
|
||||||
|
x: -50,
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
x: 0,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.05,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const childVariants: Variants = {
|
||||||
|
hiddenRight: {
|
||||||
|
opacity: 0,
|
||||||
|
x: 50,
|
||||||
|
},
|
||||||
|
hiddenLeft: {
|
||||||
|
opacity: 0,
|
||||||
|
x: -50,
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
x: 0,
|
||||||
|
transition: {
|
||||||
|
ease: "anticipate",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default function PlayerScores({ initialScoreData, player, sort, page }: Props) {
|
export default function PlayerScores({ initialScoreData, player, sort, page }: Props) {
|
||||||
const { width } = useWindowDimensions();
|
const { width } = useWindowDimensions();
|
||||||
const controls = useAnimation();
|
const controls = useAnimation();
|
||||||
|
|
||||||
const [currentSort, setCurrentSort] = useState(sort);
|
const [currentSort, setCurrentSort] = useState(sort);
|
||||||
|
const [previousPage, setPreviousPage] = useState(page);
|
||||||
const [currentPage, setCurrentPage] = useState(page);
|
const [currentPage, setCurrentPage] = useState(page);
|
||||||
const [currentScores, setCurrentScores] = useState<ScoreSaberPlayerScoresPage | undefined>(initialScoreData);
|
const [currentScores, setCurrentScores] = useState<ScoreSaberPlayerScoresPage | undefined>(initialScoreData);
|
||||||
|
|
||||||
@ -54,23 +91,18 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P
|
|||||||
staleTime: 30 * 1000, // Cache data for 30 seconds
|
staleTime: 30 * 1000, // Cache data for 30 seconds
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleAnimation = useCallback(() => {
|
const handleScoreLoad = useCallback(async () => {
|
||||||
controls.set({ x: -50, opacity: 0 });
|
await controls.start(previousPage >= currentPage ? "hiddenRight" : "hiddenLeft");
|
||||||
controls.start({ x: 0, opacity: 1, transition: { duration: 0.25 } });
|
setCurrentScores(scores);
|
||||||
}, [controls]);
|
await controls.start("visible");
|
||||||
|
}, [scores, controls]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (scores) {
|
if (scores) {
|
||||||
setCurrentScores(scores);
|
handleScoreLoad();
|
||||||
}
|
}
|
||||||
}, [scores]);
|
}, [scores]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (scores) {
|
|
||||||
handleAnimation();
|
|
||||||
}
|
|
||||||
}, [scores, handleAnimation]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newUrl = `/player/${player.id}/${currentSort}/${currentPage}`;
|
const newUrl = `/player/${player.id}/${currentSort}/${currentPage}`;
|
||||||
window.history.replaceState({ ...window.history.state, as: newUrl, url: newUrl }, "", newUrl);
|
window.history.replaceState({ ...window.history.state, as: newUrl, url: newUrl }, "", newUrl);
|
||||||
@ -89,7 +121,7 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="flex gap-2">
|
<Card className="flex gap-4">
|
||||||
<div className="flex items-center flex-row w-full gap-2 justify-center">
|
<div className="flex items-center flex-row w-full gap-2 justify-center">
|
||||||
{Object.values(scoreSort).map((sortOption, index) => (
|
{Object.values(scoreSort).map((sortOption, index) => (
|
||||||
<Button
|
<Button
|
||||||
@ -110,12 +142,17 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P
|
|||||||
{currentScores.playerScores.length === 0 && <p>No scores found. Invalid Page?</p>}
|
{currentScores.playerScores.length === 0 && <p>No scores found. Invalid Page?</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<motion.div animate={controls}>
|
<motion.div
|
||||||
<div className="grid min-w-full grid-cols-1 divide-y divide-border">
|
initial="hidden"
|
||||||
{currentScores.playerScores.map((playerScore, index) => (
|
animate={controls}
|
||||||
<Score key={index} playerScore={playerScore} />
|
variants={containerVariants}
|
||||||
))}
|
className="grid min-w-full grid-cols-1 divide-y divide-border"
|
||||||
</div>
|
>
|
||||||
|
{currentScores.playerScores.map((playerScore, index) => (
|
||||||
|
<motion.div key={index} variants={childVariants}>
|
||||||
|
<Score playerScore={playerScore} />
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<Pagination
|
<Pagination
|
||||||
@ -123,7 +160,10 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P
|
|||||||
page={currentPage}
|
page={currentPage}
|
||||||
totalPages={Math.ceil(currentScores.metadata.total / currentScores.metadata.itemsPerPage)}
|
totalPages={Math.ceil(currentScores.metadata.total / currentScores.metadata.itemsPerPage)}
|
||||||
loadingPage={isLoading ? currentPage : undefined}
|
loadingPage={isLoading ? currentPage : undefined}
|
||||||
onPageChange={setCurrentPage}
|
onPageChange={(page) => {
|
||||||
|
setPreviousPage(currentPage);
|
||||||
|
setCurrentPage(page);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user