157 lines
5.1 KiB
TypeScript
157 lines
5.1 KiB
TypeScript
import { h } from 'preact';
|
|
import { ExternalLink, Check } from 'react-feather';
|
|
import { useState } from 'preact/hooks';
|
|
import _ from 'lodash'
|
|
|
|
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">
|
|
<div class='number'>${offer.total}</div>
|
|
<div class='number'>{offer.condition}</div>
|
|
<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';
|
|
|
|
const title = accepted
|
|
? 'Click to cancel'
|
|
: 'Click to accept this offer';
|
|
|
|
return (
|
|
<button disabled={confirmed} title={title} onClick={() => setStatus()} class={classes}>${offer.total} {offer.condition}</button>
|
|
)
|
|
}
|
|
|
|
function OfferConditionSlider([condition, offers], i, groupId, rangeMin, rangeMax) {
|
|
// 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';
|
|
|
|
// const title = accepted
|
|
// ? 'Click to cancel'
|
|
// : 'Click to accept this offer';
|
|
|
|
// return (
|
|
// <button disabled={confirmed} title={title} onClick={() => setStatus()} class={classes}>${offer.total} {offer.condition}</button>
|
|
// )
|
|
|
|
const min = _.first(offers).total
|
|
const max = _.last(offers).total
|
|
// const step = min === max ? max : "any"
|
|
const step = 'any'
|
|
const id = `${groupId}-${i}`
|
|
const markersId = `${id}-markers`
|
|
const steps = offers.map(o => o.total)
|
|
|
|
const [acceptedPrice, setAcceptedPrice] = useState(0)
|
|
|
|
function onChange(target) {
|
|
const highest = () => {
|
|
return _.findLast(steps, s => target.value >= Number(s)) || 0
|
|
}
|
|
|
|
const v = highest()
|
|
setAcceptedPrice(v)
|
|
target.value = v
|
|
}
|
|
|
|
const acceptedPriceLabel = acceptedPrice ? `$${acceptedPrice}` : '-'
|
|
|
|
return (
|
|
<div key={id}>
|
|
<label for={id}>{condition}</label><br />
|
|
<label for={id}>{acceptedPriceLabel}</label><br />
|
|
<input
|
|
type="range"
|
|
id={id}
|
|
name={id}
|
|
list={markersId}
|
|
step={step}
|
|
min={rangeMin}
|
|
max={rangeMax}
|
|
value={acceptedPrice}
|
|
onChange={e => onChange((e.target as HTMLInputElement)) } />
|
|
|
|
<datalist id={markersId}>
|
|
{offers.map(o => <option value={o.total}></option>)}
|
|
</datalist>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
|
|
export default function OfferGroup(group, i) {
|
|
const ws = useSelector((state: State) => state.ws);
|
|
|
|
const format = group.details.formats[0].text ? `${group.details.formats[0].text} - ` : '';
|
|
const descriptions = group.details.formats.map(f => f.descriptions.join(' ')).join(' ')
|
|
const detailText = `${format} ${descriptions}`;
|
|
|
|
const conditions = Object.entries(_.groupBy(group.offers, 'condition'))
|
|
const rangeMin = 0
|
|
const rangeMax = _.maxBy(group.offers, 'total').total
|
|
|
|
return (
|
|
<div class="offer" key={i} id={group.details.id}>
|
|
<section>
|
|
<h3>{group.details.artists_sort} - {group.details.title} <a href={group.details.uri} target="_blank" rel="noreferrer"><ExternalLink /></a></h3>
|
|
<div class='alt-text details'>
|
|
{group.details.year} - {detailText}
|
|
</div>
|
|
<div class='alt-text details'>Status: {group.status}</div>
|
|
</section>
|
|
<img src={group.details.thumb} />
|
|
<div>
|
|
{conditions.map((c, i) => OfferConditionSlider(c, i, group.details.id, rangeMin, rangeMax))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|