want events
This commit is contained in:
1 parent
f5e75f4fe6
commit
30bf7426e4
19 files changed
+293
-108
No files matched your search
@@ -0,0 +1 @@
|
||||
This application uses Discogs’ API but is not affiliated with, sponsored or endorsed by Discogs. ‘Discogs’ is a trademark of Zink Media, LLC.
|
||||
Generated
+23
-9
@@ -12,6 +12,7 @@
|
||||
"preact": "^10.10.0",
|
||||
"preact-render-to-string": "^5.2.1",
|
||||
"preact-router": "^3.2.1",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-redux": "^8.0.2",
|
||||
"redux": "^4.2.0",
|
||||
"unistore": "^3.5.2"
|
||||
@@ -12778,7 +12779,6 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -15798,7 +15798,6 @@
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -15808,8 +15807,7 @@
|
||||
"node_modules/prop-types/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
@@ -16113,6 +16111,17 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-feather": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz",
|
||||
"integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
@@ -31062,8 +31071,7 @@
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
@@ -33326,7 +33334,6 @@
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@@ -33336,8 +33343,7 @@
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -33580,6 +33586,14 @@
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"react-feather": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz",
|
||||
"integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"preact": "^10.10.0",
|
||||
"preact-render-to-string": "^5.2.1",
|
||||
"preact-router": "^3.2.1",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-redux": "^8.0.2",
|
||||
"redux": "^4.2.0",
|
||||
"unistore": "^3.5.2"
|
||||
|
||||
@@ -49,7 +49,15 @@ const actions = {
|
||||
},
|
||||
|
||||
getWants: async function getWants() {
|
||||
return api.get('/wants');
|
||||
return api.get('/want/all');
|
||||
},
|
||||
|
||||
postWant: async function postWant(releaseId) {
|
||||
return api.post('/want', { releaseId });
|
||||
},
|
||||
|
||||
postDiscogs: async function postDiscogs(username) {
|
||||
return api.post('/want/discogs', { username });
|
||||
},
|
||||
|
||||
getLogin: async function getLogin() {
|
||||
|
||||
+4
-2
@@ -9,7 +9,8 @@ import Header from './components/header';
|
||||
import Home from './routes/home';
|
||||
import Login from './routes/login';
|
||||
import Search from './routes/search';
|
||||
import User from './routes/user';
|
||||
import List from './routes/list';
|
||||
import Offers from './routes/offers';
|
||||
|
||||
function App() {
|
||||
const [user, setUser] = useState(null);
|
||||
@@ -38,7 +39,8 @@ function App() {
|
||||
<Route path="/" component={Home} />
|
||||
<Route path="/login" component={Login} success={loginSuccess} />
|
||||
<Route path="/search" component={Search} />
|
||||
<Route path="/list/" component={User} user={user} />
|
||||
<Route path="/list" component={List} user={user} />
|
||||
<Route path="/offers" component={Offers} user={user} />
|
||||
</Router>
|
||||
</main>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Link } from 'preact-router/match';
|
||||
const Header = ({ user }) => {
|
||||
const nav = () => (
|
||||
<nav>
|
||||
<a href="/search">Offers</a>
|
||||
<a href="/">Offers</a>
|
||||
<a href='/list'>List</a>
|
||||
<a href="/search">Search</a>
|
||||
</nav>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { h } from 'preact';
|
||||
|
||||
function Want(want) {
|
||||
console.log(want);
|
||||
const r = want.data;
|
||||
|
||||
return (
|
||||
<article key={r.id}>
|
||||
<div>
|
||||
<h3>{r.artists_sort} - {r.title}</h3>
|
||||
<h5 class='alt-text' >{r.year}</h5>
|
||||
<h5 class='alt-text'>{r.country}</h5>
|
||||
<h5 class='alt-text'>{r.formats[0].descriptions.join(' ')}</h5>
|
||||
</div>
|
||||
<img src={r.thumb} />
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
export default Want;
|
||||
@@ -4,12 +4,17 @@ import { useState, useEffect } from 'preact/hooks';
|
||||
import actions from './../actions';
|
||||
import Bundle from './../components/bundle';
|
||||
|
||||
|
||||
function Home() {
|
||||
const [bundles, setBundles] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
actions.getBundles().then(setBundles);
|
||||
async function getBundles() {
|
||||
const [error, bundles] = await actions.getBundles();
|
||||
if (error) return console.error(error);
|
||||
console.log(bundles, 'bundles')
|
||||
setBundles(bundles);
|
||||
}
|
||||
getBundles();
|
||||
}, []);
|
||||
|
||||
if (!bundles.length) {
|
||||
|
||||
@@ -3,40 +3,37 @@ import { useState, useEffect } from 'preact/hooks';
|
||||
|
||||
// import style from './style.less';
|
||||
import actions from './../actions';
|
||||
import Bundle from './../components/bundle';
|
||||
import Want from './../components/want';
|
||||
|
||||
interface Props {
|
||||
user: any,
|
||||
offers: any[],
|
||||
wants: any[],
|
||||
getUserOffers: (userId: string) => void,
|
||||
}
|
||||
|
||||
const User = ({ user }: Props) => {
|
||||
const [offers, setOffers] = useState([]);
|
||||
const List = ({ user }: Props) => {
|
||||
const [wants, setOffers] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
async function getWants() {
|
||||
const [error, wants] = await actions.getWants();
|
||||
if (error) return console.error(error);
|
||||
console.log(wants, 'wants')
|
||||
setOffers(wants);
|
||||
}
|
||||
getWants();
|
||||
}, []);
|
||||
|
||||
|
||||
if (!offers.length) {
|
||||
return (
|
||||
<div class={'home'}>
|
||||
loading...
|
||||
</div>
|
||||
);
|
||||
if (!wants.length) {
|
||||
return <div> loading... </div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={'home'}>
|
||||
{offers.map(Bundle)}
|
||||
<div class="list">
|
||||
{wants.map(Want)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default User;
|
||||
export default List;
|
||||
@@ -0,0 +1,70 @@
|
||||
import { h } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import axios from 'axios';
|
||||
|
||||
import actions from '../actions';
|
||||
|
||||
function result(r) {
|
||||
function onClick() {
|
||||
actions.postWant(r.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<article key={r.id}>
|
||||
<button onClick={onClick}> + </button>
|
||||
<div>
|
||||
<h3>{r.title}</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 [results, setResults] = useState([]);
|
||||
const [noResults, setNoResults] = useState(false);
|
||||
|
||||
async function fetchResults() {
|
||||
const { data } = await actions.getBundles();
|
||||
|
||||
console.log(data);
|
||||
|
||||
if (data.length === 0) {
|
||||
setResults([]);
|
||||
return setNoResults(true);
|
||||
}
|
||||
|
||||
setNoResults(false);
|
||||
setResults(data);
|
||||
}
|
||||
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
fetchResults();
|
||||
}
|
||||
|
||||
const topEl = results.length
|
||||
? <button onClick={() => window.scrollTo(0, 0)}> top </button>
|
||||
: null;
|
||||
|
||||
const noResultsEl = noResults
|
||||
? <article>No Results</article>
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div class='search'>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div>
|
||||
{noResultsEl}
|
||||
{results.map(result)}
|
||||
{topEl}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default User;
|
||||
@@ -1,13 +1,20 @@
|
||||
import { h } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import axios from 'axios';
|
||||
import { ExternalLink } from 'react-feather';
|
||||
|
||||
import actions from '../actions';
|
||||
|
||||
function result(r) {
|
||||
function onClick() {
|
||||
actions.postWant(r.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<article key={r.id}>
|
||||
<button> + </button>
|
||||
<button onClick={onClick}> + </button>
|
||||
<div>
|
||||
<h3>{r.title}</h3>
|
||||
<h3>{r.title} <a href={`https://discogs.com${r.uri}`}><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>
|
||||
@@ -20,11 +27,12 @@ function result(r) {
|
||||
const User = () => {
|
||||
const [artist, setArtist] = useState('nine inch nails')
|
||||
const [title, setTitle] = useState('the fragile');
|
||||
const [username, setUsername] = useState('');
|
||||
const [results, setResults] = useState([]);
|
||||
const [noResults, setNoResults] = useState(false);
|
||||
|
||||
async function fetchResults() {
|
||||
const { data } = await axios.post(`http://localhost:41337/wants/search`, {
|
||||
const { data } = await axios.post(`http://localhost:41337/want/search`, {
|
||||
artist,
|
||||
title,
|
||||
});
|
||||
@@ -40,11 +48,22 @@ const User = () => {
|
||||
setResults(data);
|
||||
}
|
||||
|
||||
async function submitWantlist() {
|
||||
const [error, wants] = await actions.postDiscogs(username);
|
||||
// setNoResults(false);
|
||||
// setResults(data);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -55,14 +74,26 @@ const User = () => {
|
||||
|
||||
return (
|
||||
<div class='search'>
|
||||
<form action="" method="get">
|
||||
<label for="artist">Artist</label>
|
||||
<input type="text" name="artist" placeholder="Ben Klock" id="artist" value={artist} onChange={e => setArtist(e.target.value) } required />
|
||||
<label for="title">Title</label>
|
||||
<input type="text" name="title" placeholder="Subzero" id="title" value={title} onChange={e => setTitle(e.target.value)} required />
|
||||
<input type="submit" value="Search" onClick={handleSubmit} />
|
||||
</form>
|
||||
<div></div>
|
||||
<div>
|
||||
<form action="" method="get">
|
||||
<label for="artist">Artist</label>
|
||||
<input type="text" name="artist" placeholder="Ben Klock" id="artist" value={artist} onChange={e => setArtist(e.target.value) } required />
|
||||
<label for="title">Title</label>
|
||||
<input type="text" name="title" placeholder="Subzero" id="title" value={title} onChange={e => setTitle(e.target.value)} required />
|
||||
<input type="submit" value="Search" onClick={handleSubmit} />
|
||||
</form>
|
||||
<p>Data provided by Discogs.</p>
|
||||
<hr />
|
||||
<div>
|
||||
<p>Sync Discogs Wantlist</p>
|
||||
<form action="" method="get">
|
||||
<label for="Discogs">Discogs Username</label>
|
||||
<input type="text" name="username" placeholder="username" id="username" value={username} onChange={e => setUsername(e.target.value) } required />
|
||||
<input type="submit" value="Search" onClick={handleDiscogsSubmit} />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div />
|
||||
<div>
|
||||
{noResultsEl}
|
||||
{results.map(result)}
|
||||
|
||||
@@ -180,22 +180,36 @@ button, [type=submit] {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
article {
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
|
||||
|
||||
.search {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0.5fr 2fr;
|
||||
|
||||
article {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
background-color: var(--secondary-background-color);
|
||||
padding: var(--base-spacing);
|
||||
margin-bottom: var(--base-spacing);
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-right: var(--base-spacing);
|
||||
background: var(--tertiary-background-color);
|
||||
border-color: var(--secondary-background-color);
|
||||
}
|
||||
button {
|
||||
margin-right: var(--base-spacing);
|
||||
background: var(--tertiary-background-color);
|
||||
border-color: var(--secondary-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
|
||||
article {
|
||||
flex: 1;
|
||||
padding: var(--base-spacing);
|
||||
margin: var(--base-spacing-half);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,11 +260,11 @@ header {
|
||||
}
|
||||
|
||||
.home {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0.5fr 2fr;
|
||||
display: flex;
|
||||
|
||||
.bundle {
|
||||
flex: 1;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user