Skip to content

Commit

Permalink
Merge pull request #29 from canisterism/search
Browse files Browse the repository at this point in the history
Search
  • Loading branch information
canisterism authored Jul 22, 2023
2 parents 92d600e + f3d0bfb commit a63e945
Show file tree
Hide file tree
Showing 12 changed files with 372 additions and 99 deletions.
2 changes: 1 addition & 1 deletion backend/app/graphql/types/query_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def me
end

def game(id:)
GlobalID::Locator.locate(id)
GlobalID::Locator.locate(id) || Game.find(id)
end


Expand Down
3 changes: 2 additions & 1 deletion backend/config/initializers/cors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "http://localhost:3001", "https://clip-games.com", "https://clip-games-web.vercel.app"
origins "http://localhost:3001", "https://clip-games.com",
/\Ahttps:\/\/clip-games.+\.vercel\.app\z/

resource "*",
headers: :any,
Expand Down
106 changes: 53 additions & 53 deletions frontend/components/GameList.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,77 @@
import { GamesQuery } from "@/graphql/generated/graphql";
"use client";

import { classNames } from "@/lib/classNames";
import { StarIcon } from "@heroicons/react/20/solid";

import Image from "next/image";
import Link from "next/link";
import { useHits } from "react-instantsearch-hooks-web";

type Props = {
games: GamesQuery["games"]["nodes"];
};

export default function GameList({ games }: Props) {
if (!games) {
return <div>loading...</div>;
}
export function GameList() {
const { hits } = useHits();
return (
<div className="mx-auto max-w-10xl overflow-hidden sm:px-6 lg:px-3">
<h2 className="sr-only">Products</h2>
<h2 className="sr-only">games</h2>

<div className="-mx-px grid grid-cols-2 sm:mx-0 md:grid-cols-3 lg:grid-cols-4 xl:lg:grid-cols-8">
{games.map(
(game) =>
game && (
<div key={game.id} className="group relative p-2">
<div className="aspect-h-4 aspect-w-3 overflow-hidden rounded-lg bg-gray-200 group-hover:opacity-75">
<Image
src={
game.imageUrl
? `${game.imageUrl}`
: "https://placeimg.com/320/400/any"
}
alt={`${game.title}`}
className="h-full w-full object-cover object-center"
layout="fill"
objectFit="cover"
/>
</div>
<div className="pb-4 pt-2 ">
<h3 className="text-sm text-gray-300">
<Link href={`games/${game.id}`} passHref>
<a>
<span aria-hidden="true" className="absolute inset-0" />
{game.title}
</a>
</Link>
</h3>
<div className="mt-3 flex flex-col items-start">
<p className="sr-only">
{game.ratingAverage} out of 5 stars
</p>
<RatingStars ratingAverage={game.ratingAverage} />
<p className="mt-1 text-sm text-gray-500">
{game.reviewsCount || 0} reviews
</p>
<p className="mt-1 text-sm text-gray-500">
{game.clipsCount || 0} reviews
</p>
</div>
</div>
</div>
)
)}
{hits.map((game) => (
<Hit key={game.objectID} hit={game} />
))}
</div>
</div>
);
}

function Hit({ hit: game }: { hit: any }) {
return (
<div key={game.id} className="group relative p-2">
<div className="aspect-h-4 aspect-w-3 overflow-hidden rounded-lg bg-gray-200 group-hover:opacity-75">
<Image
src={
game.imageUrl
? `${game.imageUrl}`
: "https://placeimg.com/320/400/any"
}
alt={`${game.title}`}
className="h-full w-full object-cover object-center"
layout="fill"
objectFit="cover"
/>
</div>
<div className="pb-4 pt-2 ">
<h3 className="text-sm text-gray-300">
<Link href={`games/${game.objectID}`} passHref>
<a>
<span aria-hidden="true" className="absolute inset-0" />

{game.title}
</a>
</Link>
</h3>
<div className="mt-3 flex flex-col items-start">
<p className="sr-only">{game.ratingAverage} out of 5 stars</p>
<RatingStars ratingAverage={game.ratingTotal / game.ratingCount} />
<p className="mt-1 text-sm text-gray-500">
{game.reviewCount || 0} reviews
</p>
<p className="mt-1 text-sm text-gray-500">
{game.clipCount || 0} clips
</p>
</div>
</div>
</div>
);
}
function RatingStars({ ratingAverage }: { ratingAverage: number }) {
return (
<div className="flex items-start">
{[0, 1, 2, 3, 4].map((rating) => (
<StarIcon
key={rating}
className={classNames(
ratingAverage > rating ? "text-yellow-400" : "text-gray-100",
Math.floor(ratingAverage) > rating
? "text-yellow-400"
: "text-gray-100",
"h-5 w-5 flex-shrink-0"
)}
aria-hidden="true"
Expand Down
1 change: 0 additions & 1 deletion frontend/components/ProfileMenuIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ function ProfileMenuIcon() {
: { name: "Sign in", href: "/signin" },
];

console.log({ me, loading });
return loading ? null : (
<Menu as="div" className="relative">
<Menu.Button className="-m-1.5 flex items-center p-1.5">
Expand Down
28 changes: 28 additions & 0 deletions frontend/components/SearchBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
import { useSearchBox } from "react-instantsearch-hooks";

export default function SearchBox() {
const { query, refine } = useSearchBox();
return (
<form className="relative flex flex-1" action="#" method="GET">
<label htmlFor="search-field" className="sr-only">
Search
</label>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<MagnifyingGlassIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</div>
<input
id="search-field"
className="block h-full w-full border-0 rounded-md py-1.5 pl-10 pr-3 bg-gray-700 text-gray-200 placeholder:text-gray-400 focus:bg-white focus:text-gray-900 focus:ring-0 sm:text-sm"
placeholder="Search..."
type="search"
name="search"
onChange={(event) => refine(event.target.value)}
/>
</form>
);
}
32 changes: 3 additions & 29 deletions frontend/components/layouts/SideBarLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ProfileMenuIcon from "@/components/ProfileMenuIcon";
import SearchBox from "@/components/SearchBox";
import { Dialog, Transition } from "@headlessui/react";
import { FireIcon, MagnifyingGlassIcon } from "@heroicons/react/20/solid";
import {
Expand Down Expand Up @@ -58,11 +59,8 @@ const SideBarLayout: React.FC<Props> = ({ children }) => {

{/* Search bar */}
<div className="bg-gray-800 flex flex-1 gap-x-4 self-stretch lg:gap-x-6 py-2">
<SearchBar
onSearch={(query) => {
console.log(query);
}}
/>
<SearchBox />

<div className="flex items-center gap-x-4 lg:gap-x-6">
{/* Notification button */}
<NotificationButton />
Expand Down Expand Up @@ -107,30 +105,6 @@ function LogoLink() {
);
}

function SearchBar(props: { onSearch: (query: string) => void }) {
return (
<form className="relative flex flex-1" action="#" method="GET">
<label htmlFor="search-field" className="sr-only">
Search
</label>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<MagnifyingGlassIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</div>
<input
id="search-field"
className="block h-full w-full border-0 rounded-md py-1.5 pl-10 pr-3 bg-gray-700 text-gray-200 placeholder:text-gray-400 focus:bg-white focus:text-gray-900 focus:ring-0 sm:text-sm"
placeholder="Search..."
type="search"
name="search"
onChange={(e) => props.onSearch(e.target.value)}
/>
</form>
);
}

function NotificationButton() {
return (
<button
Expand Down
18 changes: 18 additions & 0 deletions frontend/context/algoliaContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import algoliasearch from "algoliasearch/lite";
import { InstantSearch } from "react-instantsearch-hooks-web";

const searchClient = algoliasearch(
"ARQKR6LI32",
"0a0fcaec0b67c57e920f515c98da855c"
);

const indexName =
process.env.NODE_ENV == "development"
? "development_games"
: "production_games";

export const AlgoliaContext = ({ children }: { children: React.ReactNode }) => (
<InstantSearch searchClient={searchClient} indexName={indexName} insights>
{children}
</InstantSearch>
);
1 change: 1 addition & 0 deletions frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const nextConfig = {
"placeimg.com",
"images.unsplash.com",
"lh4.googleusercontent.com",
"m.media-amazon.com",
],
},
reactStrictMode: true,
Expand Down
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@heroicons/react": "^2.0.18",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.4",
"algoliasearch": "^4.19.1",
"cookie": "^0.5.0",
"dotenv-cli": "^6.0.0",
"firebase": "^10.1.0",
Expand All @@ -27,6 +28,7 @@
"next-firebase-auth": "^1.0.0-beta.0",
"react": "18.0.0",
"react-dom": "18.0.0",
"react-instantsearch-hooks-web": "^6.47.1",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
Expand Down
9 changes: 6 additions & 3 deletions frontend/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SideBarLayout } from "@/components/layouts";
import { initAuth } from "@/config/firebase";
import { AlgoliaContext } from "@/context/algoliaContext";
import { ApolloProvider } from "@/context/apolloContext";
import { MeProvider } from "@/context/meContext";
import { withUser } from "next-firebase-auth";
Expand All @@ -13,9 +14,11 @@ function MyApp({ Component, pageProps }: AppProps) {
return (
<ApolloProvider>
<MeProvider>
<SideBarLayout>
<Component {...pageProps} />
</SideBarLayout>
<AlgoliaContext>
<SideBarLayout>
<Component {...pageProps} />
</SideBarLayout>
</AlgoliaContext>
</MeProvider>
</ApolloProvider>
);
Expand Down
4 changes: 2 additions & 2 deletions frontend/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import GameList from "@/components/GameList";
import { GameList } from "@/components/GameList";
import { createApolloClient } from "@/graphql/client";
import { NextPage } from "next";
import { withUserTokenSSR } from "next-firebase-auth";
Expand All @@ -17,7 +17,7 @@ const Home: NextPage<{ games: Games }> = ({ games }) => {
</Head>

<div className="mx-8 my-4">
<GameList games={games} />
<GameList />
</div>
</div>
);
Expand Down
Loading

0 comments on commit a63e945

Please sign in to comment.