diff --git a/frontend/components/dashboard/dashboard-view.tsx b/frontend/components/dashboard/dashboard-view.tsx index e0e0082..1f79343 100644 --- a/frontend/components/dashboard/dashboard-view.tsx +++ b/frontend/components/dashboard/dashboard-view.tsx @@ -316,6 +316,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) { >(null); const [streamFormMessage, setStreamFormMessage] = React.useState(null); + const [isFormSubmitting, setIsFormSubmitting] = React.useState(false); // --- Snapshot State (merged) --- const [snapshot, setSnapshot] = React.useState(null); @@ -556,7 +557,7 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) { } }; - const handleFormCreateStream = (event: React.FormEvent) => { + const handleFormCreateStream = async (event: React.FormEvent) => { event.preventDefault(); const hasRequiredFields = streamForm.recipient.trim() && @@ -573,15 +574,57 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) { return; } - // Convert StreamFormValues to StreamFormData for handleCreateStream if possible - // or just show alert for now as per upstream mock logic - alert( - `Stream prepared for ${streamForm.recipient} with ${streamForm.totalAmount} ${streamForm.token}. You can still edit any field before final submission integration.`, - ); - setStreamFormMessage({ - text: "Stream draft is ready for submission integration.", - tone: "success", - }); + const recipient = streamForm.recipient.trim(); + if (!/^G[A-Z0-9]{55}$/.test(recipient)) { + setStreamFormMessage({ + text: "Recipient must be a valid Stellar public key.", + tone: "error", + }); + return; + } + + const startDate = new Date(streamForm.startsAt); + const endDate = new Date(streamForm.endsAt); + if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) { + setStreamFormMessage({ + text: "Start and end times must be valid dates.", + tone: "error", + }); + return; + } + + const durationSeconds = Math.floor((endDate.getTime() - startDate.getTime()) / 1000); + if (durationSeconds <= 0) { + setStreamFormMessage({ + text: "End time must be after start time.", + tone: "error", + }); + return; + } + + setIsFormSubmitting(true); + try { + await handleCreateStream({ + recipient, + token: streamForm.token.trim(), + amount: streamForm.totalAmount.trim(), + duration: String(durationSeconds), + durationUnit: "seconds", + }); + + handleResetStreamForm(); + setStreamFormMessage({ + text: "Stream submitted to wallet and confirmed on-chain.", + tone: "success", + }); + } catch (err) { + setStreamFormMessage({ + text: toSorobanErrorMessage(err), + tone: "error", + }); + } finally { + setIsFormSubmitting(false); + } }; // ── Tab content ───────────────────────────────────────────────────────────── @@ -783,6 +826,89 @@ export function DashboardView({ session, onDisconnect }: DashboardViewProps) { placeholder="USDC" /> + + + +
+ + +
+ +
+ +
+ +