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
|
|
|
}
|