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

progress search

parent a7227722
No related branches found
No related tags found
1 merge request!46Search
Pipeline #39934 passed
import { NextResponse } from "next/server"
import { z } from "zod"
import { db } from "@/lib/db"
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const query = searchParams.get("query") as string
const querySchema = z.string().min(1)
const zod = querySchema.safeParse(query)
if (!zod.success) {
return NextResponse.json(zod.error.formErrors, { status: 400 })
}
try {
const people = await db.user.findMany({
where: {
OR: [{
username: {
contains: query,
mode: "insensitive",
},
},
{
name: {
contains: query,
mode: "insensitive",
},
}],
},
take: 3,
include: {
followers: true,
},
})
return NextResponse.json(people, { status: 200 })
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 })
}
}
\ No newline at end of file
import { NextResponse } from "next/server"
import { z } from "zod"
import { db } from "@/lib/db"
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const query = searchParams.get("query") as string
const querySchema = z.string().min(1)
const zod = querySchema.safeParse(query)
if (!zod.success) {
return NextResponse.json(zod.error.formErrors, { status: 400 })
}
try {
const people = await db.user.findMany({
where: {
OR: [{
username: {
contains: query,
mode: "insensitive",
},
},
{
name: {
contains: query,
mode: "insensitive",
},
}],
},
})
const hashtags = await db.hashtag.findMany({
where: {
text: {
contains: query,
mode: "insensitive",
},
},
})
return NextResponse.json({ people, hashtags }, { status: 200 })
} catch (error: any) {
return NextResponse.json({ error: error.message }, { status: 500 })
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@ import Link from "next/link"
import { cn } from "@/lib/utils"
import { User } from "next-auth"
import { GameUnityLogo } from "./logo"
import SearchInput from "./search-input"
import SearchInput from "./search/components/search-input"
import { Button, buttonVariants } from "./ui/button"
import { UserAccountDropdown } from "./user-nav"
......
import axios from "axios"
export const getQueryPeople = async (query: string | undefined) => {
try {
const { data } = await axios.get(`/api/search/people?query=${query}`)
return data
} catch (error: any) {
return error.Message
}
}
\ No newline at end of file
import axios from "axios"
export const getSearchResults = async (query: string) => {
try {
const { data } = await axios.get(`/api/search?query=${query}`)
return data
} catch (error: any) {
return error.message
}
}
\ No newline at end of file
import Image from "next/image";
import Link from "next/link";
import styles from "./styles/no-results.module.scss";
export const NoResults = ({ query }: { query: string | undefined }) => {
return (
<div className={styles.container}>
<div className={styles.content}>
<div className={styles.image}>
<Image
src={`/no-results.png`}
alt="no results"
width={320}
height={160}
quality={100}
loading="lazy"
/>
</div>
<h1>No results for &quot;{query}&quot;</h1>
<p>
Try searching for something else, or check your{" "}
<Link href="/settings">Search settings</Link> to see if they’re
protecting you from potentially sensitive content.
</p>
</div>
</div>
);
};
"use client"
import { Icons } from '@/components/icons'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { cn } from '@/lib/utils'
import { usePathname, useRouter } from 'next/navigation'
import { zodResolver } from '@hookform/resolvers/zod'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useState } from 'react'
import { Icons } from './icons'
import { Button } from './ui/button'
import { Input } from './ui/input'
import { toast } from './ui/use-toast'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
interface DocsSearchProps extends React.HTMLAttributes<HTMLFormElement> { }
......@@ -14,6 +16,15 @@ export default function SearchInput({ className, ...props }: DocsSearchProps) {
const [searchQuery, setSearchQuery] = useState("")
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
const search = searchParams?.get("query")?.toLowerCase() || ""
const [query, setQuery] = useState(
pathname?.split("/")[1] === "search"
? decodeURIComponent(search)
: "",
)
function onSearch(event: React.FormEvent) {
event.preventDefault()
......@@ -27,10 +38,7 @@ export default function SearchInput({ className, ...props }: DocsSearchProps) {
const encoededQuery = encodeURIComponent(searchQuery)
router.push(`${pathname}?search=${encoededQuery}`)
} else {
return toast({
title: "Work in Progress!",
description: "Sorry, but global search is not available yet... ㅤYou can test it out in the games page though!",
})
router.push(`/search?query=${searchQuery}`)
}
};
......
import { useSearchParams } from "next/navigation"
import { InfiniteGweets } from "@/components/gweets/components/infinite-gweets"
import { useGweets } from "@/components/gweets/hooks/use-gweets"
import LoadingItem from "@/components/loading-item"
import { UserItem } from "@/components/profile/components/user-item"
import { TryAgain } from "@/components/try-again"
import { useSearchPeople } from "../hooks/use-search-people"
import { NoResults } from "./no-results"
export const SearchResults = () => {
const searchParams = useSearchParams()
const query = decodeURIComponent(searchParams?.get("query") || "")
const gweets = useGweets({
queryKey: ["gweets", "query: ", query],
type: "search",
id: query,
})
const people = useSearchPeople(query)
if (gweets.isLoading || gweets.isFetching) return <LoadingItem />
if (gweets.isError) return <TryAgain />
return (
<div className="">
{gweets?.data?.pages &&
gweets?.data?.pages[0]?.gweets?.length === 0 &&
people?.data?.length === 0 ? (
<NoResults query={query} />
) : (
<div className="">
{people?.isSuccess && people?.data?.length > 0 && (
<div className="">
<h1>People</h1>
{people?.data?.map((person) => {
return <UserItem key={person?.id} user={person} sessionId={undefined} />
})}
<button className="">View All</button>
</div>
)}
<div className="">
<InfiniteGweets
gweets={gweets?.data}
hasNextPage={gweets?.hasNextPage}
fetchNextPage={gweets?.fetchNextPage}
isSuccess={gweets?.isSuccess}
isFetchingNextPage={gweets?.isFetchingNextPage}
/>
</div>
</div>
)}
</div>
)
}
\ No newline at end of file
import { IUser } from "@/components/profile/types"
import { useQuery, useQueryClient } from "@tanstack/react-query"
import { getQueryPeople } from "../api/get-query-people"
export const useSearchPeople = (query: string | undefined) => {
const queryClient = useQueryClient()
return useQuery<IUser[]>(
["people", "query: ", query],
async () => {
return getQueryPeople(query)
},
{
refetchOnWindowFocus: false,
onSuccess: (data) => {
queryClient.setQueryData(["hashtag-people"], data)
},
enabled: !!query,
},
)
}
\ No newline at end of file
import { IUser } from "@/components/profile/types"
import { IHashtag } from "@/components/trends/types"
import { useQuery } from "@tanstack/react-query"
import { getSearchResults } from "../api/get-search-results"
export const useSearch = (query: string) => {
return useQuery<{
people: IUser[]
hashtags: IHashtag[]
}>(
["search", query],
async () => {
return getSearchResults(query)
},
{
refetchOnWindowFocus: false,
enabled: !!query,
},
)
}
\ No newline at end of file
......@@ -28,6 +28,7 @@
"@t3-oss/env-nextjs": "^0.6.0",
"@tanstack/react-query": "^4.29.19",
"@uploadthing/react": "^5.1.0",
"axios": "^1.4.0",
"bcrypt": "^5.1.0",
"class-variance-authority": "^0.6.1",
"clsx": "^1.2.1",
......@@ -56,7 +57,7 @@
"@testing-library/react": "^14.0.0",
"@types/bcrypt": "^5.0.0",
"@types/jest": "^29.5.2",
"@types/node": "^20.4.0",
"@types/node": "^20.4.1",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@types/swagger-ui-react": "^4.18.0",
......@@ -3346,9 +3347,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "20.4.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.0.tgz",
"integrity": "sha512-jfT7iTf/4kOQ9S7CHV9BIyRaQqHu67mOjsIQBC3BKZvzvUB6zLxEwJ6sBE3ozcvP8kF6Uk5PXN0Q+c0dfhGX0g==",
"version": "20.4.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.1.tgz",
"integrity": "sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==",
"dev": true
},
"node_modules/@types/prettier": {
......
......@@ -33,6 +33,7 @@
"@t3-oss/env-nextjs": "^0.6.0",
"@tanstack/react-query": "^4.29.19",
"@uploadthing/react": "^5.1.0",
"axios": "^1.4.0",
"bcrypt": "^5.1.0",
"class-variance-authority": "^0.6.1",
"clsx": "^1.2.1",
......@@ -61,7 +62,7 @@
"@testing-library/react": "^14.0.0",
"@types/bcrypt": "^5.0.0",
"@types/jest": "^29.5.2",
"@types/node": "^20.4.0",
"@types/node": "^20.4.1",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@types/swagger-ui-react": "^4.18.0",
......@@ -79,4 +80,4 @@
"semver": "^7.5.3",
"optionator": "^0.9.3"
}
}
\ No newline at end of file
}
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