Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter #148

Merged
merged 9 commits into from
Dec 20, 2024
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
8 changes: 7 additions & 1 deletion app/api/games/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export async function GET(req) {
await dbConnect();

try {
const gameData = await Games.find().lean();
const { searchParams } = new URL(req.url);
const filter = searchParams.get("filter") || "";
const query = {
category: { $regex: new RegExp(filter, "i") },
};
const gameData = await Games.find(query).lean();

return NextResponse.json(gameData, { status: 200 });
} catch (error) {
Expand All @@ -17,3 +22,4 @@ export async function GET(req) {
);
}
}

36 changes: 31 additions & 5 deletions app/games/page.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
import Image from "next/image";
import Link from "next/link";
import { games } from "./data/index";
import Filter from "../../components/Filter";

export default async function page({searchParams}) {

let filterUrl
if(searchParams?.filter){
filterUrl = `${process.env.NEXT_PUBLIC_BASE_URL}/api/games?filter=${searchParams.filter}`
}else{
filterUrl = `${process.env.NEXT_PUBLIC_BASE_URL}/api/games`
}

const response = await fetch(`${filterUrl}`, {
method: "GET"
});

const gameData = await response.json()

const filterss = [{
name: 'FPS', value: 'fps'
}, {
name: 'Battle Royale', value: 'battle royale'
},{
name: "None", value: 'none'
}]

export default function page() {
return (
<section className="px-[5%] xl:px-[12%] pt-10 pb-20 transition-all">
<div className="text-4xl font-semibold mb-10 ">Games</div>
<div className="text-4xl font-semibold mb-10 flex items-center justify-between">
<h1>Games</h1>
<Filter filters={filterss} containerClasses={`border rounded-2xl`} />
</div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-5 transition-all">
{games.map((game, index) => (
{gameData.map((game, index) => (
<div key={index} className="grid ">
<Link
href={`/games/${game.id}`}
href={`/games/${game._id}`}
className="relative h-64 w-full rounded-xl hover:scale-105 transition-all"
>
<Image
src={game.image}
src={game.gameBannerPhoto}
alt={game.name}
fill
className="rounded-xl object-cover"
Expand Down
66 changes: 66 additions & 0 deletions components/Filter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client";
import React from "react";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "../components/ui/select";
import { useRouter, useSearchParams } from "next/navigation";
import { formUrlQuery } from "../lib/utils/index";

const Filter = ({ filters, otherClasses, containerClasses }) => {
const searchParams = useSearchParams();
const router = useRouter();

const paramsFilter = searchParams.get("filter");

const handleUpdateParams = (value) => {
if (value !== "none") {
const newUrl = formUrlQuery({
params: searchParams.toString(),
key: "filter",
value,
});
router.push(newUrl, { scroll: false });
} else {
router.push("/games");
}
};

return (
<div className={`relative ${containerClasses} border-zinc-200/20`}>
<Select
onValueChange={handleUpdateParams}
defaultValue={paramsFilter || undefined}
>
<SelectTrigger
className={`${otherClasses} body-regular background-light850_dark100 text-dark100_light900 min-w-16 border-none px-5 sm:w-full`}
>
<div className=" flex-1 text-nowrap text-left px-2">
<SelectValue placeholder="Filter" />
</div>
</SelectTrigger>
<SelectContent className="text-dark100_light900 small-regular border-none bg-light-1 dark:bg-dark-2 ">
<SelectGroup className="rounded-xl flex flex-col gap-1">
{filters.map((filter) => {
return (
<SelectItem
key={filter.value}
value={filter.value}
className="cursor-pointer focus:bg-light-2 dark:focus:bg-dark-4 px-2 rounded-xl border border-zinc-600/20 bg-zinc-800/40 hover:bg-black hover:border-zinc-200/50"
>
{filter.name}
</SelectItem>
);
})}
</SelectGroup>
</SelectContent>
</Select>
</div>
);
};

export default Filter;
145 changes: 145 additions & 0 deletions components/ui/select.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"use client";

import * as React from "react";
import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react";

import { cn } from "../../lib/utils";

const Select = SelectPrimitive.Root;

const SelectGroup = SelectPrimitive.Group;

const SelectValue = SelectPrimitive.Value;

const SelectTrigger = React.forwardRef(
({ className, children, ...props }, ref) => (
<SelectPrimitive.Trigger
ref={ref}
className={cn(
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
className
)}
{...props}
>
{children}
<SelectPrimitive.Icon asChild>
<ChevronDown className="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
)
);
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;

const SelectScrollUpButton = React.forwardRef(
({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
{...props}
>
<ChevronUp className="h-4 w-4" />
</SelectPrimitive.ScrollUpButton>
)
);
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;

const SelectScrollDownButton = React.forwardRef(
({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
{...props}
>
<ChevronDown className="h-4 w-4" />
</SelectPrimitive.ScrollDownButton>
)
);
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;

const SelectContent = React.forwardRef(
({ className, children, position = "popper", ...props }, ref) => (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
ref={ref}
className={cn(
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
className
)}
position={position}
{...props}
>
<SelectScrollUpButton />
<SelectPrimitive.Viewport
className={cn(
"p-1",
position === "popper" &&
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
)}
>
{children}
</SelectPrimitive.Viewport>
<SelectScrollDownButton />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
)
);
SelectContent.displayName = SelectPrimitive.Content.displayName;

const SelectLabel = React.forwardRef(
({ className, ...props }, ref) => (
<SelectPrimitive.Label
ref={ref}
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
{...props}
/>
)
);
SelectLabel.displayName = SelectPrimitive.Label.displayName;

const SelectItem = React.forwardRef(
({ className, children, ...props }, ref) => (
<SelectPrimitive.Item
ref={ref}
className={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
</SelectPrimitive.Item>
)
);
SelectItem.displayName = SelectPrimitive.Item.displayName;

const SelectSeparator = React.forwardRef(
({ className, ...props }, ref) => (
<SelectPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
)
);
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;

export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
SelectScrollUpButton,
SelectScrollDownButton,
};
15 changes: 15 additions & 0 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import qs from "query-string"


export const formUrlQuery = ({ params, key, value }) => {
const currentUrl = qs.parse(params);
currentUrl[key] = value;

return qs.stringifyUrl(
{
url: window.location.pathname,
query: currentUrl
},
{ skipNull: true }
);
};
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
"@radix-ui/react-dialog": "1.1.1",
"@radix-ui/react-dropdown-menu": "2.1.1",
"@radix-ui/react-icons": "1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-label": "2.1.0",
"@radix-ui/react-popover": "^1.1.4",
"@radix-ui/react-select": "2.1.1",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-toast": "1.2.1",
"@tabler/icons": "1.115.0",
"@tabler/icons-react": "3.11.0",
Expand Down Expand Up @@ -75,4 +75,4 @@
"prisma": {
"seed": "node prisma/seed.js"
}
}
}
Loading