Skip to content
Snippets Groups Projects
Commit eee2ca35 authored by Yusuf Akgül's avatar Yusuf Akgül :hatching_chick:
Browse files

Merge branch 'feat.BackToTopButton' into 'main'

Feat.back to top button

See merge request !12
parents 127081b1 3e2b3037
No related branches found
No related tags found
1 merge request!12Feat.back to top button
Pipeline #35290 passed
import Sort from "@/components/filter-sort-games";
import { InfiniteScrollGames } from "@/components/infinity-scroll";
import ScrollToTop from "@/components/scroll-to-top";
import SearchInput from "@/components/search-input";
// renders a list of games infinitely (presumably)
// renders a list of games infinitely
export default async function GamesPage() {
return (
<main className="relative lg:gap-10 xl:grid xl:grid-cols-[1fr_240px]">
<div className="grid">
<div className="flex flex-col gap-10 items-center w-full">
<SearchInput className="p-3 lg:w-2/3 2xl:w-1/3" />
<>
<main className="relative lg:gap-10 xl:grid xl:grid-cols-[1fr_240px]">
<div className="grid">
<div className="flex flex-col gap-10 items-center w-full">
<SearchInput className="p-3 lg:w-2/3 2xl:w-1/3" />
</div>
<InfiniteScrollGames />
</div>
<InfiniteScrollGames />
</div>
<div className="hidden xl:block flex-col md:flex">
<div className="sticky top-0">
<div className="hidden xl:block flex-col md:flex">
<Sort />
</div>
</main>
<div className="fixed top-6 left-1/2 -ml-7">
<ScrollToTop />
</div>
</main>
</>
)
}
\ No newline at end of file
......@@ -30,12 +30,12 @@ export async function GET(req: NextRequest) {
}
const games = await getGames(page,
search ? search : '',
search ? search : undefined,
category ? EGameCategory[category as keyof typeof EGameCategory] : undefined,
genre ? EGameGenres[genre as keyof typeof EGameGenres] : undefined,
filteredPlatforms,
sortby ? sortby : '',
order ? order : ''
sortby ? sortby : undefined,
order ? order : undefined
);
return NextResponse.json(games);
} catch (error) {
......
......@@ -2,7 +2,7 @@
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";
import { useState } from "react";
import { Icons } from "./icons";
import { Button } from "./ui/button";
import { Card } from "./ui/card";
......@@ -25,8 +25,8 @@ export default function Sort() {
category: selectedCategory ? `category=${selectedCategory}` : '',
genre: selectedGenre ? `genre=${selectedGenre}` : '',
platform: selectedPlatform ? `platform=${selectedPlatform}` : '',
sortMethod: selectedSortMethod ? `sortby=${selectedSortMethod}` : '',
sortOrder: selectedSortOrder ? `order=${selectedSortOrder}` : '',
sortMethod: selectedSortMethod == 'total_rating_count' ? '' : `sortby=${selectedSortMethod}`,
sortOrder: selectedSortOrder == 'desc' ? '' : `order=${selectedSortOrder}`,
};
const queryParamString = Object.values(urlParams)
......@@ -34,13 +34,9 @@ export default function Sort() {
.map((param, index) => (index === 0 ? `?${param}` : `&${param}`))
.join('');
const queryString = `${queryParamString ? `${queryParamString}` : ''}`;
const url = `${pathname}${queryParamString ? `${queryParamString}` : ''}`;
const url = `${pathname}${queryString ? `${queryString}` : ''}`;
useEffect(() => {
router.push(url);
}, [router, url]);
router.replace(url);
function toggleSortOrder() {
const newSortOrder = selectedSortOrder === 'desc' ? 'asc' : 'desc';
......@@ -53,6 +49,7 @@ export default function Sort() {
setSelectedGenre('');
setSelectedPlatform('');
setSelectedSortMethod('total_rating_count');
setSelectedSortOrder('desc');
}
return (
......
......@@ -2,6 +2,7 @@ import {
AlertTriangle,
ArrowDown,
ArrowRight,
ArrowUpToLine,
BellRing,
Check,
ChevronLeft,
......@@ -72,6 +73,7 @@ export const Icons: IconsType = {
moon: Moon, // Dark Mode Toggle Nav
arrowdown: ArrowDown, // Descending Sort
heart: Heart, // Like Button
arrowupline: ArrowUpToLine, // Back to Top Button
close: X,
spinner: Loader2,
chevronLeft: ChevronLeft,
......
......@@ -34,7 +34,7 @@ export function InfiniteScrollGames() {
fetchNextPage,
hasNextPage,
} = useInfiniteQuery(
['infiniteGames', params],
[params],
async ({ pageParam = 1 }) =>
await fetch(`/api/games/?page=${pageParam}${params}`,
).then((result) => result.json() as Promise<IGame[]>),
......@@ -49,30 +49,34 @@ export function InfiniteScrollGames() {
<Card className="p-6">
{status === 'error'
?
(<span>Error: {(error as Error).message}</span>)
(<span className="text-center">
Uh oh... something went wrong
</span>)
:
(status === 'success' && (
<InfiniteScroll
dataLength={data?.pages.length * 20}
next={fetchNextPage}
hasMore={hasNextPage ? true : false}
loader={<h4>Loading more...</h4>}
loader={
<h1 className="text-center pt-6">
<b>Trying to load more...</b>
</h1>
}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>Yay! You have seen it all</b>
</p>
<h1 className="text-center pt-6">
<b>Yay! You have seen it all!</b>
</h1>
}
>
<div className="">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8">
{data.pages.map((page, i) => (
<Fragment key={i}>
{page.map((game: IGame) => (
<Game id={game.id} name={game.name} cover={game.cover} key={game.id} />
))}
</Fragment>
))}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8">
{data.pages.map((page, i) => (
<Fragment key={i}>
{page.map((game: IGame) => (
<Game id={game.id} name={game.name} cover={game.cover} key={game.id} />
))}
</Fragment>
))}
</div>
</InfiniteScroll>
))}
......
"use client"
import { cn } from "@/lib/utils";
import { useEffect, useState } from "react";
import { Icons } from "./icons";
import { Button } from "./ui/button";
export default function ScrollToTop() {
const [isVisible, setIsVisible] = useState(false);
const toggleVisibility = () => {
if (window.pageYOffset > 300) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth"
});
};
useEffect(() => {
window.addEventListener("scroll", toggleVisibility);
return () => window.removeEventListener("scroll", toggleVisibility);
}, []);
return (
<Button size="lg" onClick={scrollToTop}
className={cn(isVisible ? "block" : "hidden", "")}>
<Icons.arrowupline className="h-3 w-3" aria-hidden="true" />
</Button>
);
}
\ No newline at end of file
......@@ -28,7 +28,7 @@ async function getToken(): Promise<IAuth> {
}
// fetches the top 200 games with a rating of 96 or higher
export async function getGames(page = 1, search?: string, category?: number, genre?: number, platform?: number[], sortby?: string, order?: string): Promise<IGame[]> {
export async function getGames(page = 1, search?: string, category?: number, genre?: number, platform?: number[], sortby = "total_rating_count", order = "desc"): Promise<IGame[]> {
const auth = await getToken();
const url = new URL(`${IGDB_BASE_URL}/games`);
......@@ -42,7 +42,7 @@ export async function getGames(page = 1, search?: string, category?: number, gen
},
body:
`fields name, cover.image_id; limit ${limit}; offset ${offset};
sort ${sortby ? sortby : "total_rating_count"} ${order ? order : "desc"};
sort ${sortby} ${order};
where total_rating_count > 3
& cover != null & total_rating != null & rating != null & age_ratings != null
& name ~ *"${search ? search : ""}"*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment