From 2e0c1feb01e64c0a5a557f2010b09ebfa1729eaf Mon Sep 17 00:00:00 2001 From: JACOB STANLEY Date: Wed, 17 Jun 2026 23:28:31 +0100 Subject: [PATCH 1/2] https://github.com/Menjay7/Remitwise-Frontend.git --- app/emergency-transfer/page.tsx | 499 ++++++++++++++++++++++++++++++-- 1 file changed, 469 insertions(+), 30 deletions(-) diff --git a/app/emergency-transfer/page.tsx b/app/emergency-transfer/page.tsx index 9960d87..6659be3 100644 --- a/app/emergency-transfer/page.tsx +++ b/app/emergency-transfer/page.tsx @@ -1,7 +1,91 @@ +"use client"; + +import { useState } from "react"; import Link from "next/link"; -import { ArrowLeft, AlertTriangle, Zap } from "lucide-react"; +import { useToast } from "@/lib/context/ToastContext"; +import { + ArrowLeft, + AlertTriangle, + Zap, + Users, + Clock, + DollarSign, + Check, + ArrowRight, + Shield, +} from "lucide-react"; +import TransactionSuccessReceipt from "@/components/TransactionSuccessReceipt"; + +type Step = "recipient" | "amount" | "review" | "confirm"; export default function EmergencyTransferPage() { + const [step, setStep] = useState("recipient"); + const [recipientName, setRecipientName] = useState(""); + const [recipientAddress, setRecipientAddress] = useState(""); + const [amount, setAmount] = useState(0); + const [currency, setCurrency] = useState("USDC"); + const [speed, setSpeed] = useState<"emergency" | "regular">("emergency"); + const [confirmedUrgent, setConfirmedUrgent] = useState(false); + const [confirmedFee, setConfirmedFee] = useState(false); + const [isSubmitted, setIsSubmitted] = useState(false); + const [transactionData, setTransactionData] = useState(null); + const { toast } = useToast(); + + const priorityFee = speed === "emergency" ? 2.0 : 0.0; + const total = amount + priorityFee; + + const handleRecipientContinue = () => { + if (recipientName && recipientAddress) { + setStep("amount"); + } + }; + + const handleAmountReview = () => { + if (amount > 0) { + setStep("review"); + } + }; + + const handleReviewConfirm = () => { + setStep("confirm"); + }; + + const handleFinalConfirm = () => { + const mockData = { + hash: "GCF27P3Q" + Math.random().toString(36).substring(2, 15).toUpperCase(), + amount: amount, + currency: currency, + recipientName: recipientName, + recipientAddress: recipientAddress, + date: new Date().toLocaleString(), + fee: priorityFee, + speed: speed, + splits: { + dailySpending: amount * 0.5, + savings: amount * 0.3, + bills: amount * 0.15, + insurance: amount * 0.05, + }, + }; + + setTransactionData(mockData); + setIsSubmitted(true); + toast({ + variant: "success", + title: "Emergency transfer submitted", + description: `Successfully sent ${amount} ${currency} to ${recipientName}. Funds will arrive in ${speed === "emergency" ? "2-5 minutes" : "30-60 minutes"}.`, + }); + }; + + if (isSubmitted && transactionData) { + return ( + setIsSubmitted(false)} + /> + ); + } + return (
{/* Header */} @@ -14,43 +98,398 @@ export default function EmergencyTransferPage() { > -

- Emergency Transfer -

+
+
+ +
+

+ Emergency Transfer +

+
-
-
-
- -
-

- Emergency Transfer Feature -

-

- This feature is currently under development. Emergency transfers - will allow you to send money instantly to your family members in - urgent situations with priority processing. -

-
- - Back to Dashboard - - - Use Regular Transfer - + {/* Progress Indicator */} +
+
+
+ + {/* Step 1 */} +
+
+ 1 +
+ Recipient +
+ + {/* Step 2 */} +
+
+ 2 +
+ Amount +
+ + {/* Step 3 */} +
+
+ 3 +
+ Review +
+ + {/* Step 4 */} +
+
+ 4 +
+ Confirm +
+
+
+ + {/* Warning Banner */} +
+
+ +
+ + Emergency Transfer Warning + + + Emergency transfers are processed immediately and{" "} + cannot be reversed. + A ${priorityFee.toFixed(2)} priority fee applies. Only use this for urgent situations. +
+ + {/* Step Content */} +
+ {step === "recipient" && ( +
+

Who are you sending to?

+ +
+
+ + setRecipientName(e.target.value)} + placeholder="Enter recipient name" + className="w-full rounded-2xl border border-zinc-800 bg-zinc-900/40 p-4 text-white placeholder:text-zinc-600 focus:border-red-500/50 focus:ring-1 focus:ring-red-500/50 outline-none transition-all" + /> +
+ +
+ + setRecipientAddress(e.target.value)} + placeholder="GXXXXXXXXXXXXXXXXXXXXXXXX" + className="w-full rounded-2xl border border-zinc-800 bg-zinc-900/40 p-4 text-white placeholder:text-zinc-600 focus:border-red-500/50 focus:ring-1 focus:ring-red-500/50 outline-none transition-all font-mono" + /> +
+
+ +
+ + Cancel + + +
+
+ )} + + {step === "amount" && ( +
+

How much to send?

+ +
+
+ +
+ setAmount(Number(e.target.value))} + placeholder="0.00" + className="w-full rounded-2xl border border-zinc-800 bg-zinc-900/40 p-4 pr-20 text-white placeholder:text-zinc-600 focus:border-red-500/50 focus:ring-1 focus:ring-red-500/50 outline-none transition-all font-semibold text-2xl" + /> + + USDC + +
+
+ +
+ + + +
+ + {amount > 0 && ( +
+
+ Transfer Amount + + {amount.toLocaleString()} USDC + +
+
+ Priority Fee + + +{priorityFee.toFixed(2)} USDC + +
+
+ Total + + {total.toLocaleString(undefined, { minimumFractionDigits: 2 })}{" "} + USDC + +
+
+ )} +
+ +
+ + +
+
+ )} + + {step === "review" && ( +
+

Review your transfer

+ +
+
+
+ Recipient + {recipientName} +
+
+ Address + + {recipientAddress.slice(0, 8)}...{recipientAddress.slice(-4)} + +
+
+ Transfer Amount + + {amount.toLocaleString()} USDC + +
+
+ Speed + + {speed === "emergency" ? "Emergency (2-5 min)" : "Regular (30-60 min)"} + +
+
+ Priority Fee + + +{priorityFee.toFixed(2)} USDC + +
+
+ Total + + {total.toLocaleString(undefined, { minimumFractionDigits: 2 })}{" "} + USDC + +
+
+ +
+
+ +
+ + Final Confirmation Required + + + This transfer cannot be reversed once submitted. Please verify all details are correct. + +
+
+
+
+ +
+ + +
+
+ )} + + {step === "confirm" && ( +
+
+
+ +
+
+

Final Confirmation

+

+ {speed === "emergency" ? "Emergency transfer - funds arrive in 2-5 minutes" : "Regular transfer - funds arrive in 30-60 minutes"} +

+
+
+ +
+
+
+ Sending to + {recipientName} +
+
+ Total Amount + + {total.toLocaleString(undefined, { minimumFractionDigits: 2 })}{" "} + USDC + +
+
+ + + + +
+ +
+ + +
+
+ )} +
); From 7a13adb02810dbfaf85ae92fc7131a9405749c48 Mon Sep 17 00:00:00 2001 From: JACOB STANLEY Date: Wed, 17 Jun 2026 23:44:58 +0100 Subject: [PATCH 2/2] feat: build out emergency transfer page with confirm-guarded flow --- components/dashboard/SixMonthTrendsWidget.tsx | 256 +++++++++++------- 1 file changed, 160 insertions(+), 96 deletions(-) diff --git a/components/dashboard/SixMonthTrendsWidget.tsx b/components/dashboard/SixMonthTrendsWidget.tsx index a63684d..43955a2 100644 --- a/components/dashboard/SixMonthTrendsWidget.tsx +++ b/components/dashboard/SixMonthTrendsWidget.tsx @@ -1,12 +1,10 @@ 'use client' -import { useCallback, useState } from 'react' import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from 'recharts' import { TrendingUp, Target, FileText } from 'lucide-react' -import WidgetEmptyState from '@/components/ui/WidgetEmptyState' -import WidgetErrorState from '@/components/ui/WidgetErrorState' -const mockChartData = [ +// Sample data for the 6-month chart (Jul-Dec) +const chartData = [ { month: 'Jul', remittances: 2800, savings: 1200, bills: 420, insurance: 80 }, { month: 'Aug', remittances: 3050, savings: 1350, bills: 400, insurance: 80 }, { month: 'Sep', remittances: 3200, savings: 1400, bills: 380, insurance: 80 }, @@ -15,6 +13,7 @@ const mockChartData = [ { month: 'Dec', remittances: 3400, savings: 1600, bills: 550, insurance: 80 }, ] +// Color scheme matching Figma design const COLORS = { remittances: '#DC2626', savings: '#B91C1C', @@ -23,7 +22,10 @@ const COLORS = { } interface CustomLegendProps { - payload?: Array<{ value: string; color: string }> + payload?: Array<{ + value: string + color: string + }> } function CustomLegend({ payload }: CustomLegendProps) { @@ -31,8 +33,14 @@ function CustomLegend({ payload }: CustomLegendProps) {
{payload?.map((entry, index) => (
-
- +
+ {entry.value}
@@ -52,6 +60,7 @@ interface SummaryCardProps { function SummaryCard({ icon, label, value, subtitle, variant = 'default', valueColor }: SummaryCardProps) { const isHighlight = variant === 'highlight' + return (
+ {/* Label row */}
-
{icon}
- +
+ {icon} +
+ {label}
-
+ + {/* Value */} +
{value}
-
{subtitle}
+ + {/* Subtitle */} +
+ {subtitle} +
) } -interface SixMonthTrendsWidgetProps { - /** Pass an empty array to show the empty state */ - chartData?: typeof mockChartData - /** Pass true to show the error state */ - hasError?: boolean -} - -export default function SixMonthTrendsWidget({ - chartData = mockChartData, - hasError = false, -}: SixMonthTrendsWidgetProps) { - const [retryKey, setRetryKey] = useState(0) - const handleRetry = useCallback(() => setRetryKey((k) => k + 1), []) - - const isEmpty = !hasError && chartData.length === 0 - +export default function SixMonthTrendsWidget() { return (
{/* Header */}
-

6-Month Trends

+

+ 6-Month Trends +

Track your financial patterns

- {!isEmpty && !hasError && ( - - )} + + {/* View Details Button */} +
- {hasError ? ( - - ) : isEmpty ? ( - - ) : ( - <> - {/* Line Chart */} -
- - - - - `$${value}`} - domain={[0, 3400]} - ticks={[0, 850, 1700, 2550, 3400]} - width={45} - /> - [`$${Number(value).toLocaleString()}`, '']} - /> - } /> - - - - - - -
+ {/* Line Chart - 320px height */} +
+ + + + + `$${value}`} + domain={[0, 3400]} + ticks={[0, 850, 1700, 2550, 3400]} + width={45} + /> + [`$${Number(value).toLocaleString()}`, '']} + /> + } /> + + + + + + +
- {/* Summary Cards */} -
-
- } label="Highest Month" value="Dec 2025" subtitle="$5,630 total" variant="highlight" /> - } label="Average" value="$5,395" subtitle="Per month" /> - } label="Growth" value="+15.7%" subtitle="vs. Jul 2025" valueColor="#DC2626" /> -
-
- - )} + {/* Summary Cards Section */} +
+
+ } + label="Highest Month" + value="Dec 2025" + subtitle="$5,630 total" + variant="highlight" + /> + } + label="Average" + value="$5,395" + subtitle="Per month" + /> + } + label="Growth" + value="+15.7%" + subtitle="vs. Jul 2025" + valueColor="#DC2626" + /> +
+
) }