offers sliders

This commit is contained in:
Nathan Rashleigh committed 2024-10-07 00:12:58 +11:00
1 parent 5e86a52d43
commit 54b1900c88
7 files changed
+46 -47

No files matched your search

+2
View File
@@ -1,5 +1,7 @@
# TODO # TODO
- accept new offers that are under highest accepted price
env env
discogs api key discogs api key
discord api key discord api key
+10 -9
View File
@@ -63,19 +63,20 @@ export default function createOffers(log: Log, pg: Pg) {
// check the user actually has this offer // check the user actually has this offer
const offer = await pg.userOfferFind(ctx.state.user, id); 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) { async function statusSet(user: User, ids: UUID[], status: Status) {
log.info({ status, id }, 'setting offer status'); log.info({ status, ids }, 'setting offer status');
const offer = await pg.offerFindId(id); // const offer = await pg.offerFindId(ids);
const update = await pg.offerStatusSet(offer.id, status); const update = await pg.offerStatusSet(ids, status);
if (status === Status.Complete) { // forget about this for now
log.info({ id, status }, 'completed offer, removing want...'); // if (status === Status.Complete) {
await pg.wantRm(offer.wantId); // log.info({ id, status }, 'completed offer, removing want...');
} // await pg.wantRm(offer.wantId);
// }
return update; return update;
} }
+3 -3
View File
@@ -289,9 +289,9 @@ export default function createPg(log: Log, prisma: PrismaClient) {
); );
} }
async function offerStatusSet(id: UUID, status: Status) { async function offerStatusSet(ids: UUID[], status: Status) {
return prisma.offer.update({ return prisma.offer.updateMany({
where: { id: id }, where: { id: { in: ids } },
data: { status }, data: { status },
}); });
} }
+4 -4
View File
@@ -75,7 +75,7 @@ export type RpcMessage =
type OfferStatusSetParams = { type OfferStatusSetParams = {
id: UUID, ids: UUID[],
status: Status, status: Status,
}; };
@@ -109,11 +109,11 @@ export default function createRpc(log: Log, pg: Pg, ws, discogs: Discogs, offers
} }
async function offerStatusSet(params: OfferStatusSetParams): Promise<OffersMessage> { async function offerStatusSet(params: OfferStatusSetParams): Promise<OffersMessage> {
const { id, status } = params; const { ids, status } = params;
assert(id, 'no id supplied'); assert(ids, 'no ids supplied');
assert(Status[status], 'unknown status'); 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); const userOffers = await offers.userOffers(user);
events.emit(Events.DiscordMessage, { msg: 'user offer event', user: user.email, offer }) events.emit(Events.DiscordMessage, { msg: 'user offer event', user: user.email, offer })
+23 -29
View File
@@ -1,6 +1,6 @@
import { h } from 'preact'; import { h } from 'preact';
import { ExternalLink, Check } from 'react-feather'; import { ExternalLink, Check } from 'react-feather';
import { useState } from 'preact/hooks'; import { useState, useCallback } from 'preact/hooks';
import _ from 'lodash' import _ from 'lodash'
import { useSelector, useDispatch } from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
@@ -60,37 +60,21 @@ function OfferPriceBtn(offer) {
} }
function OfferConditionSlider([condition, offers], i, groupId, rangeMin, rangeMax) { 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 step = 'any'
const id = `${groupId}-${i}` const id = `${groupId}-${i}`
const markersId = `${id}-markers` const markersId = `${id}-markers`
const steps = offers.map(o => o.total) 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) { function onChange(target) {
const highest = () => { const highest = () => {
@@ -98,8 +82,9 @@ function OfferConditionSlider([condition, offers], i, groupId, rangeMin, rangeMa
} }
const v = highest() const v = highest()
setAcceptedPrice(v)
target.value = v target.value = v
setAcceptedPrice(v)
sendOffers(v)
} }
const acceptedPriceLabel = acceptedPrice ? `$${acceptedPrice}` : '-' const acceptedPriceLabel = acceptedPrice ? `$${acceptedPrice}` : '-'
@@ -136,7 +121,15 @@ export default function OfferGroup(group, i) {
const conditions = Object.entries(_.groupBy(group.offers, 'condition')) const conditions = Object.entries(_.groupBy(group.offers, 'condition'))
const rangeMin = 0 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 ? (
<div class="lines">
{group.offers.map(o => OfferPriceBtn(o))}
</div>
) : null
return ( return (
<div class="offer" key={i} id={group.details.id}> <div class="offer" key={i} id={group.details.id}>
@@ -151,6 +144,7 @@ export default function OfferGroup(group, i) {
<div> <div>
{conditions.map((c, i) => OfferConditionSlider(c, i, group.details.id, rangeMin, rangeMax))} {conditions.map((c, i) => OfferConditionSlider(c, i, group.details.id, rangeMin, rangeMax))}
</div> </div>
{ buttons }
</div> </div>
) )
} }
+2
View File
@@ -350,6 +350,8 @@ main {
margin-bottom: var(--spacing); margin-bottom: var(--spacing);
} }
input[type='range']{ accent-color: var(--color-accepted); }
@media (max-width:900px) { @media (max-width:900px) {
.landing { .landing {
grid-template-columns: 1fr; grid-template-columns: 1fr;
+2 -2
View File
@@ -29,8 +29,8 @@ export default function createSocket(dispatch) {
// setTimeout(sendPing, 50); // setTimeout(sendPing, 50);
} }
function sendOfferStatusSet(id, status) { function sendOfferStatusSet(ids, status) {
send(['OfferStatusSet', { id, status }]); send(['OfferStatusSet', { ids, status }]);
} }
function sendWantRm(id) { function sendWantRm(id) {