|
|
import React, { FC, useState, useEffect } from 'react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faSearch } from '@fortawesome/free-solid-svg-icons' import { Communicator } from '../../../communicator' import classNames from 'classnames' import Gif from './gif' import { ClassDictionary, GiphyGif } from '../../../types'
const giphyIcon = require('./giphy.png') import '../../../styles/default.scss'
type APIResponse = GiphyGif[]
interface Props { communicator: Communicator }
const useDebounce = (value: string, delay = 500) => { const [valueD, setValueD] = useState(value)
useEffect(() => { const handler = setTimeout(() => { setValueD(value) }, delay)
return () => { clearTimeout(handler) } }, [value, delay])
return valueD }
const App: FC<Props> = ({ communicator }) => { const [posting, setPosting] = useState(false) const [searching, setSearching] = useState(false) const [search, setSearch] = useState('') const searchD = useDebounce(search) const [gifs, setGifs] = useState<GiphyGif[]>([]) const [selected, setSelected] = useState('')
const buttonStyle: ClassDictionary = { 'button': true, 'is-primary': true, 'is-loading': posting, }
const controlStyle: ClassDictionary = { 'control': true, 'has-icons-left': true, 'is-loading': searching, }
useEffect(() => { const init = async () => { try { const content = await communicator.init() if (content && content.parent && content.parent.data && content.parent.data.search) { setSearch(content.parent.data.search) }
await communicator.setHeight(1000) } catch (err) { console.error(err) } } init() }, [])
useEffect(() => { const doTrending = async () => { try { const response = await fetch('/api/gifs/home') setGifs(await response.json() as APIResponse) } catch (err) { console.error(err) } }
const doSearch = async () => { try { setSearching(true) const response = await fetch(`/api/gifs/search?q=${search}`) setGifs(await response.json() as APIResponse) } catch (err) { console.error(err) }
setSearching(false) }
if (!search) { doTrending() } else if (search.length > 2) { doSearch() } }, [searchD])
const handleSearchChange = (search: string) => { setSearch(search) }
const post = async () => { try { const gif = gifs.find(g => g.id === selected) if (!gif) return
setPosting(true)
await communicator.post({ attachments: [{ url: gif.images.fixed_height.url, text: gif.title, }], data: { search, }, visible: true, })
setSearch('') setSelected('') } catch (err) { console.error(err) }
setPosting(false) }
return ( <div> <div className="field"> <p className={classNames(controlStyle)}> <input className="input" type="text" placeholder="Search" value={search} onChange={(e) => handleSearchChange(e.target.value)} /> <span className="icon is-small is-left"> <FontAwesomeIcon icon={faSearch} /> </span> </p> </div>
<div className="gifs is-flex"> {gifs.map(gif => <Gif key={gif.id} gif={gif} selected={gif.id === selected} onSelect={setSelected} />)} </div>
<nav className="level"> <div className="level-left"> <div className="level-item"> <img src={giphyIcon} /> </div> </div>
<div className="level-right"> <div className="level-item"> <button className={classNames(buttonStyle)} onClick={() => post()} disabled={!selected}>Post</button> </div> </div> </nav> </div> ) }
export default App
|