diff --git a/TODO.md b/TODO.md index 276c72a..7787c0b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,7 @@ # TODO +- accept new offers that are under highest accepted price + env discogs api key discord api key diff --git a/api/src/offers.ts b/api/src/offers.ts index e7a0e11..63cc529 100644 --- a/api/src/offers.ts +++ b/api/src/offers.ts @@ -63,19 +63,20 @@ export default function createOffers(log: Log, pg: Pg) { // check the user actually has this offer const offer = await pg.userOfferFind(ctx.state.user, id); - return pg.offerStatusSet(offer.id, Status.Accepted); + return pg.offerStatusSet([offer.id], Status.Accepted); } - async function statusSet(user: User, id: UUID, status: Status) { - log.info({ status, id }, 'setting offer status'); + async function statusSet(user: User, ids: UUID[], status: Status) { + log.info({ status, ids }, 'setting offer status'); - const offer = await pg.offerFindId(id); - const update = await pg.offerStatusSet(offer.id, status); + // const offer = await pg.offerFindId(ids); + const update = await pg.offerStatusSet(ids, status); - if (status === Status.Complete) { - log.info({ id, status }, 'completed offer, removing want...'); - await pg.wantRm(offer.wantId); - } + // forget about this for now + // if (status === Status.Complete) { + // log.info({ id, status }, 'completed offer, removing want...'); + // await pg.wantRm(offer.wantId); + // } return update; } diff --git a/api/src/pg.ts b/api/src/pg.ts index 93c6e0e..a213392 100644 --- a/api/src/pg.ts +++ b/api/src/pg.ts @@ -289,9 +289,9 @@ export default function createPg(log: Log, prisma: PrismaClient) { ); } - async function offerStatusSet(id: UUID, status: Status) { - return prisma.offer.update({ - where: { id: id }, + async function offerStatusSet(ids: UUID[], status: Status) { + return prisma.offer.updateMany({ + where: { id: { in: ids } }, data: { status }, }); } diff --git a/api/src/rpc.ts b/api/src/rpc.ts index 57725ef..1c9bf52 100644 --- a/api/src/rpc.ts +++ b/api/src/rpc.ts @@ -75,7 +75,7 @@ export type RpcMessage = type OfferStatusSetParams = { - id: UUID, + ids: UUID[], status: Status, }; @@ -109,11 +109,11 @@ export default function createRpc(log: Log, pg: Pg, ws, discogs: Discogs, offers } async function offerStatusSet(params: OfferStatusSetParams): Promise { - const { id, status } = params; - assert(id, 'no id supplied'); + const { ids, status } = params; + assert(ids, 'no ids supplied'); assert(Status[status], 'unknown status'); - const offer = await offers.statusSet(user, id, status); + const offer = await offers.statusSet(user, ids, status); const userOffers = await offers.userOffers(user); events.emit(Events.DiscordMessage, { msg: 'user offer event', user: user.email, offer }) diff --git a/client/src/components/offer.group.tsx b/client/src/components/offer.group.tsx index 3c17949..6d6429d 100644 --- a/client/src/components/offer.group.tsx +++ b/client/src/components/offer.group.tsx @@ -1,6 +1,6 @@ import { h } from 'preact'; import { ExternalLink, Check } from 'react-feather'; -import { useState } from 'preact/hooks'; +import { useState, useCallback } from 'preact/hooks'; import _ from 'lodash' import { useSelector, useDispatch } from 'react-redux' @@ -60,37 +60,21 @@ function OfferPriceBtn(offer) { } 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 ( - // - // ) - - 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 initialValue = _.last(offers.filter(o => o.status === 'Accepted'))?.total || 0 - const [acceptedPrice, setAcceptedPrice] = useState(0) + const ws = useSelector((state: State) => state.ws); + const [acceptedPrice, setAcceptedPrice] = useState(initialValue) + + const sendOffers = useCallback(_.debounce(function send(v) { + const accepted = offers.filter(o => Number(o.total) <= v).map(o => o.id) + const pending = offers.filter(o => Number(o.total) > v).map(o => o.id) + ws.sendOfferStatusSet(accepted, 'Accepted') + ws.sendOfferStatusSet(pending, 'Pending') + }, 1000), []) function onChange(target) { const highest = () => { @@ -98,8 +82,9 @@ function OfferConditionSlider([condition, offers], i, groupId, rangeMin, rangeMa } const v = highest() - setAcceptedPrice(v) target.value = v + setAcceptedPrice(v) + sendOffers(v) } const acceptedPriceLabel = acceptedPrice ? `$${acceptedPrice}` : '-' @@ -136,7 +121,15 @@ export default function OfferGroup(group, i) { const conditions = Object.entries(_.groupBy(group.offers, 'condition')) const rangeMin = 0 - const rangeMax = _.maxBy(group.offers, 'total').total + const rangeMax = _.max(group.offers.map(o => Number(o.total))) + + const SHOW_BUTTONS = false + const buttons = SHOW_BUTTONS ? ( +
+ {group.offers.map(o => OfferPriceBtn(o))} +
+ ) : null + return (
@@ -151,6 +144,7 @@ export default function OfferGroup(group, i) {
{conditions.map((c, i) => OfferConditionSlider(c, i, group.details.id, rangeMin, rangeMax))}
+ { buttons }
) } diff --git a/client/src/style/styles.less b/client/src/style/styles.less index a0826ce..c5fdf3f 100644 --- a/client/src/style/styles.less +++ b/client/src/style/styles.less @@ -350,6 +350,8 @@ main { margin-bottom: var(--spacing); } +input[type='range']{ accent-color: var(--color-accepted); } + @media (max-width:900px) { .landing { grid-template-columns: 1fr; diff --git a/client/src/ws.ts b/client/src/ws.ts index 1bc0659..1b11cb7 100644 --- a/client/src/ws.ts +++ b/client/src/ws.ts @@ -29,8 +29,8 @@ export default function createSocket(dispatch) { // setTimeout(sendPing, 50); } - function sendOfferStatusSet(id, status) { - send(['OfferStatusSet', { id, status }]); + function sendOfferStatusSet(ids, status) { + send(['OfferStatusSet', { ids, status }]); } function sendWantRm(id) {