Skip to content

Commit

Permalink
pay number input (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
wraeth-eth authored Oct 25, 2023
1 parent 154dd14 commit 5da5a7d
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 9 deletions.
21 changes: 18 additions & 3 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ interface InputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
prefix?: ReactNode
prefixSeparator?: boolean
suffix?: ReactNode
suffixSeparator?: boolean
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, prefix, prefixSeparator, ...props }, ref) => {
(
{ className, prefix, prefixSeparator, suffix, suffixSeparator, ...props },
ref,
) => {
if (prefix) {
return (
<div className="focus-within:outline-bluebs-500 flex items-center rounded-lg border border-gray-300 outline-2 focus-within:outline">
<div className="flex items-center rounded-lg border border-gray-300 bg-white outline-2 focus-within:outline focus-within:outline-bluebs-500">
<div
className={twMerge(
'h-full py-2 pl-3 text-base leading-6 text-gray-500',
Expand All @@ -20,6 +25,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
>
{prefix}
</div>

<input
ref={ref}
className={twMerge(
Expand All @@ -28,6 +34,15 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
)}
{...props}
/>

<div
className={twMerge(
'h-full py-2 pr-3 text-base leading-6 text-gray-500',
suffixSeparator ? 'border-l border-gray-300 pl-3' : '',
)}
>
{suffix}
</div>
</div>
)
}
Expand All @@ -36,7 +51,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
ref={ref}
className={twMerge(
'focus:outline-bluebs-500 w-full rounded-lg border border-gray-300 px-3 py-2 text-base text-gray-900 placeholder:text-gray-400',
'w-full rounded-lg border border-gray-300 px-3 py-2 text-base text-gray-900 placeholder:text-gray-400 focus:outline-bluebs-500',
className,
)}
{...props}
Expand Down
78 changes: 72 additions & 6 deletions src/components/Project/components/ProjectPayForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ import {
FormMessage,
} from '@/components/ui/Form'
import { zodResolver } from '@hookform/resolvers/zod'
import { PropsWithChildren, useCallback, useMemo } from 'react'
import { PropsWithChildren, useCallback, useMemo, useState } from 'react'
import { useForm } from 'react-hook-form'
import { twMerge } from 'tailwind-merge'
import { z } from 'zod'
import { useProjectPay } from '../providers/ProjectPayContext'
import { useJbProject } from '@/hooks/useJbProject'
import { formatEther } from 'juice-hooks'
import { Ether, formatEther } from 'juice-hooks'
import { EthereumIconFilled } from '@/components/icon/EthereumIconFilled'
import { ChevronDownIcon } from '@heroicons/react/24/solid'
import { parseEther } from 'viem'
import { isNumber } from 'lodash'

const WEI = 1e-18

const formSchema = z.object({
paymentAmount: z
paymentAmount: z.coerce
.number()
.min(WEI, 'Payment amount must be greater than 1e-18 (1 wei)'),
// TODO: make more robust for eth addresses / ENS
Expand Down Expand Up @@ -50,6 +54,10 @@ export const ProjectPayForm: React.FC<ProjectPayFormProps> = ({
},
})

// TODO: Use proper currency formatting from juice_hooks when available
// for now, 1n == eth, 2n == usd
const [currency, setCurrency] = useState<1n | 2n>(1n)

const totalNftSelectionPrice = useMemo(
() =>
nftRewardIds.reduce((acc, nftId) => {
Expand All @@ -65,8 +73,14 @@ export const ProjectPayForm: React.FC<ProjectPayFormProps> = ({
console.log(values)
}, [])

// TODO
const total = totalNftSelectionPrice
const paymentAmount = form.watch('paymentAmount')

// TODO - Account for usd conversion
const total =
totalNftSelectionPrice +
(paymentAmount && !isNaN(paymentAmount)
? parseEther(`${paymentAmount}`)
: 0n)

return (
<Form {...form}>
Expand All @@ -79,7 +93,12 @@ export const ProjectPayForm: React.FC<ProjectPayFormProps> = ({
name="paymentAmount"
render={({ field }) => (
<ProjectPayFormItem label="Payment amount">
<Input {...field} />
<ProjectPayAmountInput
currency={currency}
setCurrency={setCurrency}
placeholder="0"
{...field}
/>
</ProjectPayFormItem>
)}
/>
Expand Down Expand Up @@ -158,3 +177,50 @@ const ProjectPayFormItem: React.FC<
</FormItem>
)
}

type ProjectPayAmountInputProps = {
currency: 1n | 2n
setCurrency: (currency: 1n | 2n) => void
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'>

const ProjectPayAmountInput: React.FC<ProjectPayAmountInputProps> = ({
className,
currency,
setCurrency,
...props
}) => {
const isEth = currency === 1n
const toggleCurrency = useCallback(() => {
setCurrency(isEth ? 2n : 1n)
}, [isEth, setCurrency])

return (
<Input
prefix={
isEth ? (
<EthereumIconFilled className="h-7 w-7 rounded-full bg-bluebs-50 fill-bluebs-500 p-1" />
) : (
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-green-100 text-green-600">
$
</div>
)
}
suffix={
<Button
type="button"
size="child"
variant="secondary"
className={twMerge(
'flex gap-1 rounded-sm py-1.5 pl-1 pr-2 text-xs',
!isEth && 'bg-green-100 text-green-600',
)}
onClick={toggleCurrency}
>
<ChevronDownIcon className="h-4 w-4" />
{isEth ? 'ETH' : 'USD'}
</Button>
}
{...props}
/>
)
}

0 comments on commit 5da5a7d

Please sign in to comment.