diff --git a/frontend/.storybook/main.ts b/frontend/.storybook/main.ts index bec4e50..c6535af 100644 --- a/frontend/.storybook/main.ts +++ b/frontend/.storybook/main.ts @@ -1,4 +1,4 @@ -import type { StorybookConfig } from '@storybook/nextjs'; +import type { StorybookConfig } from '@storybook/nextjs-vite'; const config: StorybookConfig = { stories: [ @@ -11,7 +11,7 @@ const config: StorybookConfig = { '@storybook/addon-a11y', '@chromatic-com/storybook', ], - framework: '@storybook/nextjs', + framework: '@storybook/nextjs-vite', staticDirs: ['../public'], }; diff --git a/frontend/app/sandbox/playground/page.tsx b/frontend/app/sandbox/playground/page.tsx index fa21742..9fe1a18 100644 --- a/frontend/app/sandbox/playground/page.tsx +++ b/frontend/app/sandbox/playground/page.tsx @@ -26,8 +26,8 @@ export default function PlaygroundPage() { const [loading, setLoading] = useState(false); const client = new BridgeletClient({ - baseUrl: process.env.NEXT_PUBLIC_API_BASE_URL, - apiKey: process.env.NEXT_PUBLIC_API_KEY, + baseUrl: process.env[`NEXT_PUBLIC_API_BASE_URL`], + apiKey: process.env[`NEXT_PUBLIC_API_KEY`], } as BridgeletClientOptions); const handleEndpointChange = (endpoint: Endpoint) => { @@ -49,18 +49,18 @@ export default function PlaygroundPage() { let result: unknown; switch (selected) { case "getClaimDetails": - result = await client.getClaimDetails(params.token); + result = await client.getClaimDetails(params[`token`] ?? ""); break; case "createPaymentIntent": result = await client.createPaymentIntent({ - senderPublicKey: params.senderPublicKey, - amountStroops: params.amountStroops, - assetCode: params.assetCode, + senderPublicKey: params[`senderPublicKey`] ?? "", + amountStroops: params[`amountStroops`] ?? "", + assetCode: params[`assetCode`] ?? "", }); break; case "redeemClaim": - result = await client.redeemClaim(params.token, { - recipientPublicKey: params.recipientPublicKey, + result = await client.redeemClaim(params[`token`] ?? "", { + recipientPublicKey: params[`recipientPublicKey`] ?? "", }); break; } diff --git a/frontend/components/claim-status-card.stories.tsx b/frontend/components/claim-status-card.stories.tsx index d6fe077..a14d08f 100644 --- a/frontend/components/claim-status-card.stories.tsx +++ b/frontend/components/claim-status-card.stories.tsx @@ -10,18 +10,14 @@ export default meta; type Story = StoryObj; -export const Loading: Story = { - args: { status: 'loading' }, -}; - -export const Unclaimed: Story = { - args: { status: 'unclaimed', amount: '100', asset: 'USDC', expiresAt: '2026-07-15T12:00:00Z' }, +export const Available: Story = { + args: { status: 'available', amountStroops: '1000000000', assetCode: 'USDC', expiresAt: '2026-07-15T12:00:00Z' }, }; export const Claimed: Story = { - args: { status: 'claimed', amount: '100', asset: 'USDC' }, + args: { status: 'claimed' }, }; export const Expired: Story = { - args: { status: 'expired', amount: '50', asset: 'XLM', expiresAt: '2026-06-01T00:00:00Z' }, -}; + args: { status: 'expired', expiresAt: '2026-06-01T00:00:00Z', supportEmail: 'support@bridgelet.com' }, +}; \ No newline at end of file diff --git a/frontend/components/claim-status-card.tsx b/frontend/components/claim-status-card.tsx index 58cdb00..048c59d 100644 --- a/frontend/components/claim-status-card.tsx +++ b/frontend/components/claim-status-card.tsx @@ -142,7 +142,7 @@ function AvailablePanel({ type="button" onClick={handleClaim} disabled={claiming} - className="w-full rounded-lg bg-green-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-green-700 disabled:opacity-60 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" + className="w-full rounded-lg bg-green-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-green-700 disabled:opacity-60 focus-visible:outline focus-visible:outline-offset-2 focus-visible:outline-green-600" > {claiming ? 'Claiming…' : 'Claim now'} diff --git a/frontend/components/send-form/steps/confirm-step.tsx b/frontend/components/send-form/steps/confirm-step.tsx index dd4c49a..8a8b8cb 100644 --- a/frontend/components/send-form/steps/confirm-step.tsx +++ b/frontend/components/send-form/steps/confirm-step.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import type { SendFormState } from '../index'; import { useNfc } from '@/hooks/use-nfc'; +import { createPaymentIntent } from '@/lib/bridgelet'; type ConfirmStepProps = { state: SendFormState; @@ -20,10 +21,19 @@ export function ConfirmStep({ state, onBack }: ConfirmStepProps) { setSubmitting(true); setError(null); try { - // Placeholder: wire up to POST /api/accounts + POST /send in a real impl. - await new Promise((res) => setTimeout(res, 800)); - // Set a mock claim URL for the NFC experiment since the backend isn't wired - setClaimUrl('https://bridgelet.example.com/claim/mock-token-123'); + const amountStroops = Math.round(Number.parseFloat(state.amountXlm) * 10_000_000).toString(); + const response = await createPaymentIntent({ + senderPublicKey: state.publicKey, + amountStroops, + assetCode: state.assetCode, + memo: state.memo || undefined, + }); + + const resolvedClaimUrl = response.claimUrl.startsWith('http') + ? response.claimUrl + : `${window.location.origin}${response.claimUrl}`; + + setClaimUrl(resolvedClaimUrl); setSubmitted(true); } catch (err) { setError(err instanceof Error ? err.message : 'Something went wrong.'); @@ -44,7 +54,22 @@ export function ConfirmStep({ state, onBack }: ConfirmStepProps) { A claim link has been sent to {state.recipientEmail}. They have 24 hours to claim their funds.

- + + {claimUrl && ( +
+

Claim link

+ + {claimUrl} + +
+ )} + {isSupported && claimUrl && (