feat: add improved pi agent with observatory, dashboard, and pledge-now-pay-later
This commit is contained in:
97
pledge-now-pay-later/src/app/p/[token]/steps/amount-step.tsx
Normal file
97
pledge-now-pay-later/src/app/p/[token]/steps/amount-step.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
|
||||
const PRESETS = [1000, 2000, 5000, 10000, 25000, 50000] // pence
|
||||
|
||||
interface Props {
|
||||
onSelect: (amountPence: number) => void
|
||||
eventName: string
|
||||
}
|
||||
|
||||
export function AmountStep({ onSelect, eventName }: Props) {
|
||||
const [custom, setCustom] = useState("")
|
||||
const [selected, setSelected] = useState<number | null>(null)
|
||||
|
||||
const handlePreset = (amount: number) => {
|
||||
setSelected(amount)
|
||||
setCustom("")
|
||||
}
|
||||
|
||||
const handleCustomChange = (value: string) => {
|
||||
const clean = value.replace(/[^0-9.]/g, "")
|
||||
setCustom(clean)
|
||||
setSelected(null)
|
||||
}
|
||||
|
||||
const handleContinue = () => {
|
||||
const amount = selected || Math.round(parseFloat(custom) * 100)
|
||||
if (amount >= 100) onSelect(amount)
|
||||
}
|
||||
|
||||
const isValid = selected || (custom && parseFloat(custom) >= 1)
|
||||
|
||||
return (
|
||||
<div className="max-w-md mx-auto pt-4 space-y-8">
|
||||
<div className="text-center space-y-2">
|
||||
<h1 className="text-3xl font-extrabold text-gray-900">
|
||||
Make a Pledge
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
for <span className="font-semibold text-foreground">{eventName}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Presets */}
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
{PRESETS.map((amount) => (
|
||||
<button
|
||||
key={amount}
|
||||
onClick={() => handlePreset(amount)}
|
||||
className={`
|
||||
tap-target rounded-2xl border-2 py-4 text-center font-bold text-lg transition-all
|
||||
${selected === amount
|
||||
? "border-trust-blue bg-trust-blue text-white shadow-lg shadow-trust-blue/25 scale-[1.02]"
|
||||
: "border-gray-200 bg-white text-gray-900 hover:border-trust-blue/50 active:scale-[0.98]"
|
||||
}
|
||||
`}
|
||||
>
|
||||
£{amount / 100}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Custom */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-muted-foreground">Or enter a custom amount</label>
|
||||
<div className="relative">
|
||||
<span className="absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-gray-400">£</span>
|
||||
<Input
|
||||
type="text"
|
||||
inputMode="decimal"
|
||||
placeholder="0.00"
|
||||
value={custom}
|
||||
onChange={(e) => handleCustomChange(e.target.value)}
|
||||
className="pl-10 h-16 text-2xl font-bold text-center rounded-2xl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Continue */}
|
||||
<Button
|
||||
size="xl"
|
||||
className="w-full"
|
||||
disabled={!isValid}
|
||||
onClick={handleContinue}
|
||||
>
|
||||
Continue →
|
||||
</Button>
|
||||
|
||||
<p className="text-center text-xs text-muted-foreground">
|
||||
You won't be charged now. Choose how to pay next.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user