mtg-visual-search/app/page.tsx

124 lines
3.7 KiB
TypeScript
Raw Normal View History

2024-05-24 01:16:02 +00:00
"use client"
import {
Button,
CircularProgress,
Grid,
Input,
Sheet,
Stack,
Typography,
} from "@mui/joy"
import { FormEvent, useState } from "react"
import { CardType } from "@/types/types"
import InfiniteScroll from "react-infinite-scroller"
2024-05-23 21:18:39 +00:00
export default function Home() {
2024-05-24 01:16:02 +00:00
const [searchQuery, setSearchQuery] = useState("")
const [loading, setLoading] = useState(false)
const [cards, setCards] = useState<CardType[]>([])
const [cardsDisplayed, setCardsDisplayed] = useState<CardType[]>([])
const handleSubmit = async (e: FormEvent) => {
e.preventDefault()
setLoading(true)
const response = await fetch(`/api/?search=${searchQuery}`)
const data = await response.json()
setCards(data)
setCardsDisplayed(data.slice(0, 12))
setLoading(false)
}
const loadMore = async () => {
if (cardsDisplayed.length >= cards.length) return
setCardsDisplayed(
cards.slice(0, Math.min(cardsDisplayed.length + 12, cards.length))
)
}
2024-05-23 21:18:39 +00:00
return (
2024-05-24 01:16:02 +00:00
<Sheet
sx={{
padding: 5,
minHeight: "100vh",
}}
>
<Stack
spacing={2}
alignItems="center"
justifyContent="center"
textAlign="center"
>
{!cards?.length && (
<>
<Typography level="h1">Search MTG Artwork</Typography>
<Typography level="h4">
For best results use simple words, separated by spaces.
</Typography>
<Typography>
Search will return all cards that match at least one of the words,
so use many similar words to broaden your search.
</Typography>
</>
)}
<form
onSubmit={handleSubmit}
style={{ width: "100%", maxWidth: "700px" }}
2024-05-23 21:18:39 +00:00
>
2024-05-24 01:16:02 +00:00
<Input
placeholder="Type something..."
size="lg"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
endDecorator={
<Button
variant="solid"
color="primary"
size="lg"
type="submit"
loading={loading}
sx={{ borderTopLeftRadius: 0, borderBottomLeftRadius: 0 }}
>
Search
</Button>
}
sx={{ width: "100%" }} // Add this line to make the search bar full width
/>
</form>
{!!cards?.length && (
<InfiniteScroll
pageStart={0}
initialLoad={false}
loadMore={loadMore}
hasMore={cardsDisplayed.length < cards.length}
loader={<CircularProgress />}
>
<Grid container spacing={2} sx={{ flexGrow: 1 }} key="cardGrid">
{cardsDisplayed.map((card) => (
<Grid xs={12} sm={6} md={4} lg={3} xl={2} key={card.id}>
<a href={card.url} target="_blank" rel="noreferrer">
<img
src={card.mediumImageUrl}
alt={card.name}
style={{
width: "100%",
borderRadius: 16,
transition: "transform 0.1s",
}}
onMouseOver={(e) =>
((e.target as HTMLImageElement).style.transform =
"scale(1.1)")
}
onMouseOut={(e) =>
((e.target as HTMLImageElement).style.transform =
"scale(1)")
}
/>
</a>
</Grid>
))}
</Grid>
</InfiniteScroll>
)}
</Stack>
</Sheet>
)
2024-05-23 21:18:39 +00:00
}