offers sliders
This commit is contained in:
1 parent
5e86a52d43
commit
54b1900c88
7 files changed
+46
-47
No files matched your search
@@ -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
@@ -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
@@ -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
@@ -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 })
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
Reference in new issue
Block a user