bundle offers grouped
This commit is contained in:
1 parent
7946259550
commit
623d0f3938
12 files changed
+228
-148
No files matched your search
@@ -0,0 +1,75 @@
|
||||
import { h } from 'preact';
|
||||
import { ExternalLink, Check } from 'react-feather';
|
||||
import { useState } from 'preact/hooks';
|
||||
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
import { State } from './../store';
|
||||
|
||||
import http from '../http';
|
||||
|
||||
function OfferLine(offer) {
|
||||
const ws = useSelector((state: State) => state.ws);
|
||||
|
||||
function setStatus(status) {
|
||||
ws.sendOfferStatusSet(offer.id, status);
|
||||
}
|
||||
|
||||
const accepted = offer.status === 'Accepted';
|
||||
const classes = `${accepted ? 'accepted' : ''}`;
|
||||
const btnText = accepted
|
||||
? offer.status
|
||||
: 'Accept';
|
||||
|
||||
const negBtn = accepted
|
||||
? <button onClick={() => setStatus('Pending')} class='neg'>Cancel</button>
|
||||
: <button onClick={() => setStatus('Declined')} class='neg'>Decline</button>;
|
||||
|
||||
return (
|
||||
<div class="line">
|
||||
<span class='number'>${offer.total}</span>
|
||||
<button onClick={() => setStatus('Accepted')} disabled={accepted} class={classes} >{btnText}</button>
|
||||
{negBtn}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function OfferPriceBtn(offer) {
|
||||
const ws = useSelector((state: State) => state.ws);
|
||||
const accepted = offer.status === 'Accepted';
|
||||
const confirmed = offer.status === 'Confirmed';
|
||||
|
||||
function setStatus() {
|
||||
if (accepted) return ws.sendOfferStatusSet(offer.id, 'Pending')
|
||||
ws.sendOfferStatusSet(offer.id, 'Accepted');
|
||||
}
|
||||
|
||||
const classes = `${accepted ? 'accepted' : ''} ${confirmed ? 'confirmed' : ''}`;
|
||||
const btnText = accepted
|
||||
? offer.status
|
||||
: 'Accept';
|
||||
|
||||
return (
|
||||
<button disabled={confirmed} onClick={() => setStatus()} class={classes}>${offer.total} {offer.condition}</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default function WantOffers(wantOffers) {
|
||||
const ws = useSelector((state: State) => state.ws);
|
||||
|
||||
const details = wantOffers[0].want.data;
|
||||
|
||||
return (
|
||||
<div class="offer">
|
||||
<section>
|
||||
<h3>{details.artists_sort} - {details.title} <a href={details.uri} target="_blank"><ExternalLink /></a></h3>
|
||||
<div class='alt-text' >{details.year}</div>
|
||||
<div class='alt-text'>{details.formats.map(f => f.descriptions.join(' ')).join(' ')}</div>
|
||||
</section>
|
||||
<img src={details.thumb} />
|
||||
<div class="lines">
|
||||
{wantOffers.map(o => OfferPriceBtn(o))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -15,6 +15,7 @@ const Info = () => {
|
||||
<h2>How It Works</h2>
|
||||
<p> First, add some records to your <span class='alt'>List</span> on the <a href='/search'>Search Page</a>. </p>
|
||||
<p> Mates Crates will then make <span class='alt'>Offers</span> to you for releases you add to your <a href='/list'>List</a>. </p>
|
||||
<p> Select all <span class='alt'>Offers</span> you are interested in, the more you accept the more likely the item will be <span class='alt-text'>Confirmed</span>.</p>
|
||||
<p> Check back regularly for updated <span class='alt'>Offers</span>, the global record marketplace is a living thing. </p>
|
||||
</section>
|
||||
|
||||
@@ -33,12 +34,8 @@ const Info = () => {
|
||||
|
||||
<section>
|
||||
<h2>FAQ</h2>
|
||||
<h3> Record Condition </h3>
|
||||
<p> All Mates Crates offers are for records that are either mint or very good condition. </p>
|
||||
<h3> Delivery Times </h3>
|
||||
<p> Records are usually available for pickup within a week. We order in bulk, which often means express, insured shipping to Melbourne. </p>
|
||||
<h3> Duplicates </h3>
|
||||
<p> Sometimes we can get a record from multiple sources, these appear as duplicate offers. Accepting multiple offers increases the chance the item will be confirmed. </p>
|
||||
<h3> Friends </h3>
|
||||
<p> Please invite other collectors to the site. More users means offers can become cheaper and shipped sooner. </p>
|
||||
</section>
|
||||
|
||||
@@ -6,34 +6,23 @@ import { useSelector, useDispatch } from 'react-redux'
|
||||
import http from './../http';
|
||||
import { State, offersState } from './../store';
|
||||
|
||||
import Offer from './../components/offer';
|
||||
import WantOffers from './../components/want.offers';
|
||||
|
||||
function Home() {
|
||||
const dispatch = useDispatch()
|
||||
const offers = useSelector((state: State) => state.offers);
|
||||
|
||||
useEffect(() => {
|
||||
async function getOffers() {
|
||||
const [error, offers] = await http.getOffers();
|
||||
if (error) return console.error(error);
|
||||
dispatch(offersState.actions.set(offers));
|
||||
if (offers.length === 0) route('/search');
|
||||
}
|
||||
getOffers();
|
||||
}, []);
|
||||
|
||||
if (!offers.length) {
|
||||
return (
|
||||
<div class={'offers'}>
|
||||
loading...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// if (!offers.length) {
|
||||
// return (
|
||||
// <div class={'offers'}>
|
||||
// loading...
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<div class={'offers'}>
|
||||
{offers.map(Offer)}
|
||||
{Object.values(offers).map(WantOffers)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+93
-74
@@ -56,7 +56,7 @@ html {
|
||||
font-family:var(--base-font-family);
|
||||
line-height:var(--base-line-height);
|
||||
-webkit-text-size-adjust:100%;
|
||||
background:var(--base-background-color);
|
||||
background:var(--background-0);
|
||||
box-sizing:border-box
|
||||
}
|
||||
|
||||
@@ -65,23 +65,6 @@ html {
|
||||
--breakpoint-medium: 35em;
|
||||
--breakpoint-large: 56em;
|
||||
|
||||
--color-dark-blue: #101014;
|
||||
--color-mid-blue: #16171d;
|
||||
--color-light-blue: #1f2128;
|
||||
--color-mid-grey: #9BA0B3;
|
||||
--color-off-white: #F4F1D0;
|
||||
--color-accent-blue: #5E9ED6;
|
||||
|
||||
--color-blue-gray: #506485;
|
||||
--color-green: #537a34;
|
||||
|
||||
--base-accent-color: var(--color-accent-blue);
|
||||
--fg-color: var(--color-off-white);
|
||||
--hover-link-color: var(--color-off-white);
|
||||
--base-background-color: var(--color-dark-blue);
|
||||
--secondary-background-color: var(--color-mid-blue);
|
||||
--tertiary-background-color: var(--color-light-blue);
|
||||
|
||||
--small-font-size: 0.75em;
|
||||
--base-font-size: 1em;
|
||||
--smedium-font-size: 1.333em;
|
||||
@@ -96,9 +79,6 @@ html {
|
||||
--base-line-height: 1.4;
|
||||
--header-line-height: 1.2;
|
||||
|
||||
--min-font-size: var(--base-font-size);
|
||||
--max-font-size: var(--large-font-size);
|
||||
|
||||
--base-border-color: var(--secondary-font-color);
|
||||
--base-border: 2px solid var(--base-border-color);
|
||||
--hover-border: 2px solid var(--base-font-color);
|
||||
@@ -107,11 +87,37 @@ html {
|
||||
--base-focus: 2px solid var(--base-accent-color);
|
||||
--base-outline-offset: 0.25em;
|
||||
|
||||
--base-spacing: 1rem;
|
||||
--base-spacing-half: calc(var(--base-spacing)/2);
|
||||
--base-spacing-double: calc(var(--base-spacing)*2);
|
||||
--min-font-size: var(--base-font-size);
|
||||
--max-font-size: var(--large-font-size);
|
||||
|
||||
--utility-bar-header-height: calc(var(--base-spacing) * 1.5);
|
||||
--color-dark-blue: #101014;
|
||||
--color-mid-blue: #16171d;
|
||||
--color-light-blue: #1f2128;
|
||||
--color-mid-grey: #9BA0B3;
|
||||
--color-off-white: #F4F1D0;
|
||||
--color-accent-blue: #5E9ED6;
|
||||
|
||||
--color-blue-gray: #506485;
|
||||
|
||||
--color-blue: #475977;
|
||||
--color-green: #476d4a;
|
||||
|
||||
--color-accepted: var(--color-blue);
|
||||
--color-confirmed: var(--color-green);
|
||||
|
||||
--base-accent-color: var(--color-accent-blue);
|
||||
--fg-color: var(--color-off-white);
|
||||
--hover-link-color: var(--color-off-white);
|
||||
|
||||
--background-0: var(--color-dark-blue);
|
||||
--background-1: var(--color-mid-blue);
|
||||
--background-2: var(--color-light-blue);
|
||||
|
||||
--spacing: 1rem;
|
||||
--spacing-half: calc(var(--spacing)/2);
|
||||
--spacing-double: calc(var(--spacing)*2);
|
||||
|
||||
--utility-bar-header-height: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
|
||||
button, input, optgroup, select, textarea {
|
||||
@@ -136,11 +142,11 @@ input:focus, textarea:focus {
|
||||
}
|
||||
|
||||
button, input {
|
||||
overflow:visible
|
||||
overflow:visible;
|
||||
}
|
||||
|
||||
button, select {
|
||||
text-transform:none
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
button, [type=button], [type=reset], [type=submit] {
|
||||
@@ -154,7 +160,7 @@ button, [type=button], [type=reset], [type=submit] {
|
||||
text-transform: uppercase;
|
||||
|
||||
&:hover {
|
||||
background: var(--tertiary-background-color);
|
||||
background: var(--background-2);
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
@@ -165,33 +171,33 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom:var(--base-spacing);
|
||||
margin-bottom:var(--spacing);
|
||||
font-size:var(--large-font-size)
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom:var(--base-spacing);
|
||||
margin-bottom:var(--spacing);
|
||||
font-size:var(--medium-font-size);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom:calc(var(--base-spacing)/2);
|
||||
margin-bottom:calc(var(--spacing)/2);
|
||||
font-size:var(--smedium-font-size)
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom:calc(var(--base-spacing)/3);
|
||||
margin-bottom:calc(var(--spacing)/3);
|
||||
font-size:var(--base-font-size)
|
||||
}
|
||||
|
||||
p {
|
||||
margin:0 0 var(--base-spacing)
|
||||
margin:0 0 var(--spacing)
|
||||
}
|
||||
|
||||
// ok actual styles
|
||||
|
||||
body {
|
||||
padding-top: calc(var(--base-spacing)/2);
|
||||
padding-top: calc(var(--spacing)/2);
|
||||
}
|
||||
|
||||
main {
|
||||
@@ -199,8 +205,8 @@ main {
|
||||
}
|
||||
|
||||
button, [type=submit] {
|
||||
padding: var(--base-spacing-half);
|
||||
background: var(--secondary-background-color);
|
||||
padding: var(--spacing-half);
|
||||
background: var(--background-1);
|
||||
|
||||
}
|
||||
|
||||
@@ -222,7 +228,7 @@ button, [type=submit] {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
section {
|
||||
margin-bottom: var(--base-spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
}
|
||||
|
||||
.contact {
|
||||
@@ -237,10 +243,10 @@ button, [type=submit] {
|
||||
}
|
||||
|
||||
article {
|
||||
background-color: var(--secondary-background-color);
|
||||
background-color: var(--background-1);
|
||||
|
||||
button {
|
||||
border-color: var(--tertiary-background-color);
|
||||
border-color: var(--background-2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,15 +256,15 @@ article {
|
||||
|
||||
article {
|
||||
display: grid;
|
||||
padding: var(--base-spacing);
|
||||
margin-bottom: var(--base-spacing);
|
||||
padding: var(--spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-right: var(--base-spacing);
|
||||
background: var(--tertiary-background-color);
|
||||
border-color: var(--secondary-background-color);
|
||||
margin-right: var(--spacing);
|
||||
background: var(--background-2);
|
||||
border-color: var(--background-1);
|
||||
|
||||
&.added {
|
||||
background: var(--color-green);
|
||||
@@ -270,7 +276,10 @@ article {
|
||||
.list {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
1fr 1fr 1fr 1fr;
|
||||
1fr 1fr 1fr;
|
||||
|
||||
grid-row-gap: var(--spacing);
|
||||
grid-column-gap: var(--spacing);
|
||||
|
||||
article {
|
||||
display: grid;
|
||||
@@ -284,6 +293,7 @@ article {
|
||||
"remove remove";
|
||||
|
||||
button {
|
||||
margin-top: var(--spacing-half);
|
||||
grid-area: remove
|
||||
}
|
||||
|
||||
@@ -291,13 +301,12 @@ article {
|
||||
grid-area: details;
|
||||
}
|
||||
|
||||
padding: var(--base-spacing);
|
||||
margin: var(--base-spacing-half);
|
||||
padding: var(--spacing);
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: var(--base-spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
|
||||
label, input {
|
||||
display: block;
|
||||
@@ -308,15 +317,15 @@ form {
|
||||
}
|
||||
|
||||
input {
|
||||
padding: var(--base-spacing-half);
|
||||
margin-bottom: var(--base-spacing);
|
||||
padding: var(--spacing-half);
|
||||
margin-bottom: var(--spacing);
|
||||
}
|
||||
|
||||
label {
|
||||
font-family: var(--secondary-font-family);
|
||||
font-size: var(--small-font-size);
|
||||
text-transform: uppercase;
|
||||
margin-bottom: var(--base-spacing-half);
|
||||
margin-bottom: var(--spacing-half);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -334,7 +343,7 @@ a {
|
||||
nav {
|
||||
a {
|
||||
font-size: var(--small-font-size);
|
||||
margin-right: var(--base-spacing);
|
||||
margin-right: var(--spacing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +351,7 @@ nav {
|
||||
header {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr min-content;
|
||||
padding-bottom: var(--base-spacing);
|
||||
padding-bottom: var(--spacing);
|
||||
|
||||
a {
|
||||
white-space: nowrap;
|
||||
@@ -353,10 +362,10 @@ header {
|
||||
flex-flow: row;
|
||||
|
||||
.bundle {
|
||||
margin-bottom: var(--base-spacing-double);
|
||||
margin-bottom: var(--spacing-double);
|
||||
|
||||
section {
|
||||
margin-bottom: var(--base-spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
}
|
||||
|
||||
.items {
|
||||
@@ -364,14 +373,14 @@ header {
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
|
||||
div {
|
||||
margin-right: var(--base-spacing);
|
||||
margin-bottom: var(--base-spacing);
|
||||
margin-right: var(--spacing);
|
||||
margin-bottom: var(--spacing);
|
||||
|
||||
display: grid;
|
||||
|
||||
&.bold {
|
||||
font-weight: bold;
|
||||
background: var(--tertiary-background-color);
|
||||
background: var(--background-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,13 +394,14 @@ header {
|
||||
.offer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr min-content;
|
||||
grid-template-rows: 1fr min-content;
|
||||
grid-template-areas:
|
||||
"details img"
|
||||
"btn neg";
|
||||
"lines lines";
|
||||
|
||||
padding: var(--base-spacing);
|
||||
margin: var(--base-spacing-half);
|
||||
background: var(--secondary-background-color);
|
||||
padding: var(--spacing);
|
||||
margin: var(--spacing-half);
|
||||
background: var(--background-1);
|
||||
|
||||
section {
|
||||
grid-area: details;
|
||||
@@ -400,22 +410,31 @@ header {
|
||||
img {
|
||||
grid-area: img;
|
||||
justify-self: end;
|
||||
margin-left: var(--base-spacing-half);
|
||||
margin-left: var(--spacing-half);
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: var(--base-spacing-half);
|
||||
grid-area: btn;
|
||||
border-color: var(--tertiary-background-color);
|
||||
.lines {
|
||||
grid-area: lines;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: var(--spacing-half);
|
||||
|
||||
&.accepted {
|
||||
background: var(--color-accent-blue);
|
||||
cursor: auto;
|
||||
}
|
||||
button {
|
||||
margin-top: var(--spacing-half);
|
||||
border-color: var(--background-2);
|
||||
|
||||
&.neg {
|
||||
margin-left: var(--base-spacing-half);
|
||||
grid-area: neg;
|
||||
&.accepted {
|
||||
background: var(--color-accepted);
|
||||
}
|
||||
|
||||
&.confirmed {
|
||||
cursor: auto;
|
||||
background: var(--color-confirmed);
|
||||
}
|
||||
|
||||
&.neg {
|
||||
margin-left: var(--spacing-half);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user