Adding in modal for card detail when card is clicked. Working through styling, and working with NextJS.

This commit is contained in:
Frank Delaguila
2022-11-04 15:40:07 -06:00
parent a7d15cc120
commit a036c449f7
6 changed files with 106 additions and 25 deletions

View File

@@ -5,25 +5,31 @@ import styles from '../styles/Home.module.css';
import React, { useEffect, useState, useMemo } from 'react';
import { debounce } from 'lodash';
import Modal from '../components/modal';
export default function Home() {
const [search, setSearch] = useState('');
const [selectedCard, setSelectedCard] = useState({});
const [cards, setCards] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [queryParams, setQueryParams] = useState('');
const [modalOpen, setModalOpen] = useState(false);
const searchForCard = async (event: React.ChangeEvent<HTMLInputElement>) => {
event.stopPropagation();
setSearch(event.target.value);
setLoading(true);
await fetch(`https://api.scryfall.com/cards/search?q=${encodeURIComponent(event.target.value)}`)
if( event.target.value !== '' ) {
await fetch(`https://api.scryfall.com/cards/search?q=${encodeURIComponent(event.target.value)}`)
.then( res => res.json() )
.then( ({data}) => {
setCards(data);
setLoading(false);
})
.catch( err => console.log(err) );
.catch( err => setError(err) );
}
};
const debounceSearch = useMemo( () => debounce(searchForCard, 300), [search] );
@@ -34,39 +40,48 @@ export default function Home() {
return (
<div>
<Head>
<title>Magic Card Valuator</title>
</Head>
<div className={`bg-center bg-no-repeat flex justify-center items-center mb-4 h-96 ${styles.hero}`}>
<div className="w-3/4 text-center">
<div className="absolute bg-red-800 w-96 bg-red-800 right-0 top-0 rounded-md mr-4 mt-4 p-4">
{error}
</div>
<div className={`bg-center bg-no-repeat flex justify-center items-center h-96 ${styles.hero}`}>
<div className="container text-center">
<label htmlFor="search" className="block mx-auto font-bold mb-2 text-2xl">Search for a Magic Card</label>
<input id="search" name="search" type="text" className={`block w-1/2 mx-auto rounded-full py-2 px-4 ${styles.search}`} onChange={debounceSearch} />
<input id="search" name="search" type="text" className={`block w-full md:w-1/2 mx-auto rounded-full py-2 px-4 ${styles.search}`} onChange={debounceSearch} />
</div>
</div>
<main className="container">
<section className="flex flex-wrap">
{loading && !cards.length ?
<div className="spinner"></div>
:
cards && cards.map( (card: any) => <Image className="hover:scale-110 transition-transform duration-150 ease-in-out w-1/6 p-2" key={card.id} alt={`${card.name} Card`} src={card.image_uris?.png || "https://via.placeholder.com/150" } width={100} height={100} /> )
}
</section>
<main className="container my-4">
{ cards?.length === 0 || !cards ?
<div>Please search for a card</div>
:
<section className="flex flex-wrap justify-center items-center">
{loading && search !== "" ?
<div className="spinner mx-auto"></div>
:
cards && cards.map( (card: any) => <Image onClick={() => {
setSelectedCard(card);
setModalOpen(true);
}} className="cursor-pointer hover:scale-110 transition-transform duration-150 ease-in-out w-full sm:w-1/2 md:w-1/3 lg:w-1/4 p-2" key={card.id} alt={`${card.name} Card`} src={card.image_uris?.png || "https://via.placeholder.com/150" } width={100} height={100} /> )
}
</section>
}
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
href="https://www.linkedin.com/in/frank-delaguila/"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span>
<Image className="fill-white" src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
rel="noopener noreferrer">
Frank Delaguila
</a>
</footer>
{modalOpen ?
<Modal open={setModalOpen} />
: null}
</div>
)
}