Skip to content

Commit

Permalink
feat: QoL features
Browse files Browse the repository at this point in the history
  • Loading branch information
PatrickAlphaC committed Feb 12, 2025
1 parent 496cf5b commit 3260a51
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 38 deletions.
99 changes: 67 additions & 32 deletions src/components/AirdropForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP
},
],
})



// TODO: See what's in error to see what we should display to user.
const { data: hash, isPending, error, writeContract } = useWriteContract()
const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({
Expand All @@ -58,33 +61,34 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP

// This should be a promise, this is weird wagmi design
if (result < total) {
writeContract({
await writeContract({
abi: erc20Abi,
address: tokenAddress as `0x${string}`,
functionName: "approve",
args: [tSenderAddress as `0x${string}`, total.toString()],
})
// {
// // onSuccess: () => { console.log("Approved!") },
// onError: (error) => {
// alert("Error approving, see console!")
// console.log(error)
// },
// // onSettled: () => { console.log("wtf") }
// })
},
{
onSuccess: () => {
writeContract({
abi: tsenderAbi,
address: tSenderAddress as `0x${string}`,
functionName: "airdropERC20",
args: [
tokenAddress,
// Comma or new line separated
recipients.split(/[,\n]+/).map(addr => addr.trim()).filter(addr => addr !== ''),
amounts.split(/[,\n]+/).map(amt => amt.trim()).filter(amt => amt !== ''),
total.toString(),
],
})
},
onError: (error) => {
console.log(error)
},
// onSettled: () => { }
})
}

writeContract({
abi: tsenderAbi,
address: tSenderAddress as `0x${string}`,
functionName: "airdropERC20",
args: [
tokenAddress,
recipients.split(","),
amounts.split(",").map(amt => amt.trim()),
total.toString(),
],
})
}

async function getApprovedAmount(tSenderAddress: string | null): Promise<number> {
Expand Down Expand Up @@ -116,10 +120,41 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP
<span>Waiting for confirmation...</span>
</div>
)
if (error) {
console.log(error)
return (
<div className="flex items-center justify-center gap-2 w-full">
<CgSpinner className="animate-spin" size={20} />
<span>Error, see console.</span>
</div>
)
}
if (isConfirmed) return "Transaction confirmed."
return isUnsafeMode ? "Send Tokens (Unsafe)" : "Send Tokens"
}

useEffect(() => {
const savedTokenAddress = localStorage.getItem('tokenAddress')
const savedRecipients = localStorage.getItem('recipients')
const savedAmounts = localStorage.getItem('amounts')

if (savedTokenAddress) setTokenAddress(savedTokenAddress)
if (savedRecipients) setRecipients(savedRecipients)
if (savedAmounts) setAmounts(savedAmounts)
}, [])

useEffect(() => {
localStorage.setItem('tokenAddress', tokenAddress)
}, [tokenAddress])

useEffect(() => {
localStorage.setItem('recipients', recipients)
}, [recipients])

useEffect(() => {
localStorage.setItem('amounts', amounts)
}, [amounts])

return (
<div
className={`max-w-2xl min-w-full xl:min-w-lg w-full lg:mx-auto p-6 flex flex-col gap-6 bg-white rounded-xl ring-[4px] border-2 ${isUnsafeMode ? " border-red-500 ring-red-500/25" : " border-blue-500 ring-blue-500/25"}`}
Expand All @@ -142,17 +177,20 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP
<InputForm
label="Token Address"
placeholder="0x"
value={tokenAddress}
onChange={e => setTokenAddress(e.target.value)}
/>
<InputForm
label="Recipients (comma separated)"
label="Recipients (comma or new line separated)"
placeholder="0x123..., 0x456..."
value={recipients}
onChange={e => setRecipients(e.target.value)}
large={true}
/>
<InputForm
label="Amounts (wei, comma separated)"
label="Amounts (wei; comma or new line separated)"
placeholder="100, 200, 300..."
value={amounts}
onChange={e => setAmounts(e.target.value)}
large={true}
/>
Expand Down Expand Up @@ -204,11 +242,10 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP
)}

<button
className={`cursor-pointer flex items-center justify-center w-full py-3 rounded-[9px] text-white transition-colors font-semibold relative border ${
isUnsafeMode
? "bg-red-500 hover:bg-red-600 border-red-500"
: "bg-blue-500 hover:bg-blue-600 border-blue-500"
}`}
className={`cursor-pointer flex items-center justify-center w-full py-3 rounded-[9px] text-white transition-colors font-semibold relative border ${isUnsafeMode
? "bg-red-500 hover:bg-red-600 border-red-500"
: "bg-blue-500 hover:bg-blue-600 border-blue-500"
}`}
onClick={handleSubmit}
disabled={isPending}
>
Expand All @@ -218,11 +255,9 @@ export default function AirdropForm({ isUnsafeMode, onModeChange }: AirdropFormP
<div className="absolute w-full inset-0 mix-blend-overlay z-10 inner-shadow rounded-lg" />
{/* White inner border */}
<div className="absolute w-full inset-0 mix-blend-overlay z-10 border-[1.5px] border-white/20 rounded-lg" />
{isPending
{isPending || error || isConfirming
? getButtonContent()
: isConfirming
? getButtonContent()
: isUnsafeMode
: isUnsafeMode
? "Send Tokens (Unsafe)"
: "Send Tokens"}
</button>
Expand Down
3 changes: 1 addition & 2 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import { ConnectButton } from "@rainbow-me/rainbowkit"
import { FaGithub } from "react-icons/fa"
import Image from "next/image"
import logo from "/public/T-Sender.svg"

export default function Header() {
return (
<nav className="px-8 py-4.5 border-b-[1px] border-zinc-100 flex flex-row justify-between items-center bg-white xl:min-h-[77px]">
<div className="flex items-center gap-2.5 md:gap-6">
<a href="/" className="flex items-center gap-1 text-zinc-800">
<Image src={logo} alt="TSender" width={36} height={36} />
<Image src="/T-Sender.svg" alt="TSender" width={36} height={36} />
<h1 className="font-bold text-2xl hidden md:block">TSender</h1>
</a>
<a
Expand Down
4 changes: 3 additions & 1 deletion src/components/ui/InputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@ export interface InputFormProps {
onChange?: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void
}

export function InputForm({ label, placeholder, type, large, onChange }: InputFormProps) {
export function InputForm({ label, placeholder, value, type, large, onChange }: InputFormProps) {
return (
<div className="flex flex-col gap-1.5">
<label className="text-zinc-600 font-medium text-sm">{label}</label>
{large ? (
<textarea
className={`bg-white py-2 px-3 border border-zinc-300 placeholder:text-zinc-500 text-zinc-900 shadow-xs rounded-lg focus:ring-[4px] focus:ring-zinc-400/15 focus:outline-none h-24 align-text-top`}
placeholder={placeholder}
value={value || ''}
onChange={onChange}
/>
) : (
<input
className={`bg-white py-2 px-3 border border-zinc-300 placeholder:text-zinc-500 text-zinc-900 shadow-xs rounded-lg focus:ring-[4px] focus:ring-zinc-400/15 focus:outline-none`}
type={type}
placeholder={placeholder}
value={value || ''}
onChange={onChange}
/>
)}
Expand Down
4 changes: 2 additions & 2 deletions src/utils/calculateTotal/calculateTotal.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export function calculateTotal(amounts: string): number {
const amountArray = amounts
.split(",")
.split(/[,\n]+/)
.map(amt => amt.trim())
.filter(amt => amt !== "")
.map(amt => parseFloat(amt))
if (amountArray.some(isNaN)) {
return 0
}
return amountArray.reduce((acc, curr) => acc + curr, 0)
}
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
"include": [
"**/*.ts",
"**/*.tsx",
".fleek/types/**/*.ts",
".next/types/**/*.ts",
"next-env.d.ts",
".fleek/types/**/*.ts"
"out/types/**/*.ts"
],
"exclude": [
"node_modules"
Expand Down

0 comments on commit 3260a51

Please sign in to comment.