stacker.news/components/item-act.js

119 lines
3.2 KiB
JavaScript
Raw Normal View History

2023-07-24 18:35:05 +00:00
import Button from 'react-bootstrap/Button'
import InputGroup from 'react-bootstrap/InputGroup'
2023-07-13 03:08:32 +00:00
import React, { useState, useRef, useEffect, useCallback } from 'react'
import { Form, Input, SubmitButton } from './form'
2021-09-12 16:55:38 +00:00
import { useMe } from './me'
2022-12-09 20:13:31 +00:00
import UpBolt from '../svgs/bolt.svg'
2023-02-08 19:38:04 +00:00
import { amountSchema } from '../lib/validate'
2023-07-13 03:08:32 +00:00
import { useAnonymous } from '../lib/anonymous'
import { useShowModal } from './modal'
import FundError from './fund-error'
2021-09-10 18:55:36 +00:00
2023-05-14 23:33:49 +00:00
const defaultTips = [100, 1000, 10000, 100000]
2023-05-14 23:11:31 +00:00
const Tips = ({ setOValue }) => {
const tips = [...getCustomTips(), ...defaultTips].sort((a, b) => a - b)
return tips.map(num =>
2023-05-14 23:11:31 +00:00
<Button
size='sm'
2023-07-24 18:35:05 +00:00
className={`${num > 1 ? 'ms-2' : ''} mb-2`}
2023-05-14 23:11:31 +00:00
key={num}
onClick={() => { setOValue(num) }}
>
<UpBolt
2023-07-24 18:35:05 +00:00
className='me-1'
2023-05-14 23:11:31 +00:00
width={14}
height={14}
/>{num}
</Button>)
}
2023-07-25 14:14:45 +00:00
const getCustomTips = () => JSON.parse(window.localStorage.getItem('custom-tips')) || []
2023-05-14 23:11:31 +00:00
const addCustomTip = (amount) => {
2023-05-14 23:33:49 +00:00
if (defaultTips.includes(amount)) return
2023-05-14 23:11:31 +00:00
let customTips = Array.from(new Set([amount, ...getCustomTips()]))
if (customTips.length > 3) {
customTips = customTips.slice(0, 3)
}
2023-07-25 14:14:45 +00:00
window.localStorage.setItem('custom-tips', JSON.stringify(customTips))
2023-05-14 23:11:31 +00:00
}
export default function ItemAct ({ onClose, itemId, act, strike }) {
2021-09-10 18:55:36 +00:00
const inputRef = useRef(null)
2021-09-12 16:55:38 +00:00
const me = useMe()
2022-12-09 20:13:31 +00:00
const [oValue, setOValue] = useState()
const showModal = useShowModal()
2021-09-10 18:55:36 +00:00
useEffect(() => {
inputRef.current?.focus()
}, [onClose, itemId])
2021-09-10 18:55:36 +00:00
2023-07-13 03:08:32 +00:00
const submitAct = useCallback(
async (amount, invoiceHash) => {
2023-07-13 03:08:32 +00:00
if (!me) {
const storageKey = `TIP-item:${itemId}`
const existingAmount = Number(window.localStorage.getItem(storageKey) || '0')
window.localStorage.setItem(storageKey, existingAmount + amount)
}
await act({
variables: {
id: itemId,
sats: Number(amount),
invoiceHash
2023-07-13 03:08:32 +00:00
}
})
await strike()
addCustomTip(Number(amount))
onClose()
}, [act, onClose, strike, itemId])
const anonAct = useAnonymous(submitAct)
2021-09-10 18:55:36 +00:00
return (
<Form
initial={{
amount: me?.tipDefault,
default: false
}}
2023-02-08 19:38:04 +00:00
schema={amountSchema}
onSubmit={async ({ amount }) => {
try {
await anonAct(amount)
} catch (error) {
if (error.toString().includes('insufficient funds')) {
showModal(onClose => {
return (
<FundError
onClose={onClose}
amount={amount}
onPayment={submitAct}
/>
)
})
return
}
throw new Error({ message: error.toString() })
}
2021-09-10 18:55:36 +00:00
}}
>
<Input
label='amount'
name='amount'
2023-05-14 23:24:45 +00:00
type='number'
innerRef={inputRef}
overrideValue={oValue}
required
autoFocus
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
/>
<div>
2023-05-14 23:11:31 +00:00
<Tips setOValue={setOValue} />
</div>
<div className='d-flex'>
2023-07-24 18:35:05 +00:00
<SubmitButton variant='success' className='ms-auto mt-1 px-4' value='TIP'>zap</SubmitButton>
</div>
</Form>
2021-09-10 18:55:36 +00:00
)
}