124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import { h } from 'preact';
|
|
import { useState, useRef, useEffect } from 'preact/hooks';
|
|
import { ExternalLink, Check } from 'react-feather';
|
|
import { useSelector } from 'react-redux'
|
|
|
|
import { State } from './../store';
|
|
|
|
import http from '../http';
|
|
|
|
function Result(r, wants) {
|
|
const [added, setAdded] = useState(false)
|
|
|
|
async function onClick() {
|
|
const [error, want] = await http.postWant(r.id);
|
|
if (error) return false;
|
|
setAdded(true);
|
|
}
|
|
|
|
const wanted = wants.some(w => w.release === r.id);
|
|
|
|
const classes = `${added || wanted ? 'added' : ''}`;
|
|
const btnText = added
|
|
? <Check />
|
|
: '+';
|
|
|
|
return (
|
|
<article key={r.id}>
|
|
<button onClick={onClick} disabled={added} class={classes} >{btnText}</button>
|
|
<div>
|
|
<h3>{r.title} <a href={`https://discogs.com${r.uri}`} target="_blank"><ExternalLink /></a></h3>
|
|
<h5 class='alt-text' >{r.year}</h5>
|
|
<h5 class='alt-text'>{r.country}</h5>
|
|
<h5 class='alt-text'>{r.format.join(' ')}</h5>
|
|
</div>
|
|
<img src={r.thumb} />
|
|
</article>
|
|
);
|
|
}
|
|
|
|
const User = () => {
|
|
const [query, setQuery] = useState('')
|
|
const [title, setTitle] = useState('');
|
|
const [username, setUsername] = useState('');
|
|
const [results, setResults] = useState([]);
|
|
const [infoText, setInfoText] = useState('');
|
|
|
|
const wants = useSelector((state: State) => state.wants);
|
|
|
|
async function fetchResults() {
|
|
const [error, results] = await http.postWantSearch(query);
|
|
|
|
if (results.length === 0) {
|
|
setResults([]);
|
|
return setInfoText('No results');
|
|
}
|
|
|
|
setInfoText('');
|
|
setResults(results);
|
|
}
|
|
|
|
async function submitWantlist() {
|
|
const [error, wants] = await http.postDiscogs(username);
|
|
if (wants.length === 0) {
|
|
setResults([]);
|
|
return setInfoText('No new additions');
|
|
}
|
|
|
|
setInfoText(`Added ${wants.length} items to your list.`);
|
|
}
|
|
|
|
const searchRef = useRef<HTMLInputElement>()
|
|
|
|
useEffect(() => {
|
|
searchRef.current.focus()
|
|
}, [])
|
|
|
|
function handleSubmit(e) {
|
|
e.preventDefault();
|
|
fetchResults();
|
|
}
|
|
|
|
function handleDiscogsSubmit(e) {
|
|
e.preventDefault();
|
|
submitWantlist();
|
|
}
|
|
|
|
const topEl = results.length
|
|
? <button onClick={() => window.scrollTo(0, 0)}> top </button>
|
|
: null;
|
|
|
|
const infoEl = infoText
|
|
? <article><div></div><div>{infoText}</div></article>
|
|
: null;
|
|
|
|
return (
|
|
<div class='search'>
|
|
<div>
|
|
<form action="" method="get">
|
|
<label for="query">Query</label>
|
|
<input type="text" name="query" ref={searchRef} placeholder="ben klock subzero" id="query" value={query} onChange={e => setQuery((e.target as HTMLInputElement).value) } required />
|
|
<input type="submit" value="Search" onClick={handleSubmit} />
|
|
</form>
|
|
<hr />
|
|
<div>
|
|
<form action="" method="get">
|
|
<label for="Discogs">Discogs Username</label>
|
|
<input type="text" name="username" placeholder="Discogs Username" id="username" value={username} onChange={e => setUsername((e.target as HTMLInputElement).value) } required />
|
|
<input type="submit" value="Sync Wantlist" onClick={handleDiscogsSubmit} />
|
|
</form>
|
|
</div>
|
|
<hr />
|
|
<p>Data provided by Discogs.</p>
|
|
</div>
|
|
<div class='results'>
|
|
{infoEl}
|
|
{results.map(r => Result(r, wants))}
|
|
{topEl}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default User;
|