Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions frontend/app/components/FAQ.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';
"use client";

import React, { useState, useRef, useEffect } from 'react';
import clsx from 'clsx';
import { Button } from '@/app/components/ui/Button';

interface FAQItem {
question: string;
Expand Down Expand Up @@ -65,8 +66,10 @@ const FAQ: React.FC = () => {
: "bg-white/[0.03] border-white/[0.08] hover:border-[rgba(0,212,192,0.3)]"
)}
>
<button
className="w-full flex items-center justify-between gap-4 px-6 py-5 bg-transparent border-none cursor-pointer text-left transition-colors duration-200 hover:bg-white/[0.02] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[#00d4c0] focus-visible:-outline-offset-[2px] focus-visible:rounded-xl"
<Button
variant="ghost"
size="md"
className="w-full flex items-center justify-between gap-4 px-6 py-5 bg-transparent border-none text-left transition-colors duration-200 hover:bg-white/[0.02] focus-visible:rounded-xl"
onClick={() => toggleItem(index)}
aria-expanded={openIndex === index}
aria-controls={`faq-answer-${index}`}
Expand All @@ -78,7 +81,7 @@ const FAQ: React.FC = () => {
>
{openIndex === index ? '×' : '+'}
</span>
</button>
</Button>

<div
// I put the id={`faq-answer-${index}`} as against onInvalid={...} cause of errors
Expand Down
22 changes: 13 additions & 9 deletions frontend/app/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Loader2, Wallet } from "lucide-react";
import { Wallet } from "lucide-react";
import ThemeToggle from "./ThemeToggle";
import { useWallet } from "../context/WalletContext";
import { useToast } from "../context/ToastContext";
import { Button } from "./ui/Button";
import { useFocusTrap } from "../hooks/useFocusTrap";

interface NavLink {
Expand Down Expand Up @@ -120,16 +121,16 @@ const Navbar: React.FC = () => {
}

return (
<button
type="button"
<Button
variant="primary"
size="md"
onClick={connect}
disabled={isLoading}
loading={isLoading}
title={error ?? undefined}
className={`inline-flex items-center justify-center gap-2 rounded-full border-none bg-[var(--color-accent)] px-6 py-3 text-sm font-semibold text-[#061a1a] shadow-sm hover:brightness-105 disabled:cursor-not-allowed disabled:opacity-60 disabled:hover:brightness-100 ${mobile ? "mt-4 w-full" : "hidden sm:inline-flex"}`}
className={`rounded-full ${mobile ? "mt-4 w-full" : "hidden sm:inline-flex"}`}
>
{isLoading ? <Loader2 size={14} className="animate-spin" /> : null}
{isLoading ? "Connecting..." : "Connect Wallet"}
</button>
</Button>
);
};

Expand Down Expand Up @@ -170,11 +171,14 @@ const Navbar: React.FC = () => {
<ThemeToggle compact className="hidden md:flex" />
<WalletButton />

<Button
variant="secondary"
size="sm"
<button
ref={menuButtonRef}
type="button"
onClick={() => setIsMobileMenuOpen((open) => !open)}
className="inline-flex items-center justify-center rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-2 text-[var(--color-text-muted)] hover:text-[var(--color-text)] md:hidden"
className="md:hidden p-2"
aria-expanded={isMobileMenuOpen}
aria-controls="mobile-menu"
aria-label={isMobileMenuOpen ? "Close navigation menu" : "Open navigation menu"}
Expand Down Expand Up @@ -208,7 +212,7 @@ const Navbar: React.FC = () => {
/>
</svg>
)}
</button>
</Button>
</div>
</div>
</div>
Expand Down
15 changes: 4 additions & 11 deletions frontend/app/components/Newsletter.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"use client";

import React, { useState } from "react";
import { Button } from "./ui/Button";

const Newsletter: React.FC = () => {
const [email, setEmail] = useState("");

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (email) {
// TODO: Implement newsletter subscription
// Send the email to your backend API
setEmail("");
}
};
Expand All @@ -29,9 +28,7 @@ const Newsletter: React.FC = () => {
onSubmit={handleSubmit}
>
<div className="flex-1 max-w-[400px] max-md:max-w-full">
<label htmlFor="newsletter-email" className="sr-only">
Email address
</label>
<label htmlFor="newsletter-email" className="sr-only">Email address</label>
<input
id="newsletter-email"
type="email"
Expand All @@ -43,13 +40,9 @@ const Newsletter: React.FC = () => {
aria-describedby="newsletter-help"
/>
</div>
<button
type="submit"
className="px-6 py-3 bg-[#00d1c1] text-[#020c0c] border-none rounded-md text-sm font-semibold cursor-pointer transition-all duration-200 hover:opacity-90 active:scale-[0.98]"
aria-label="Subscribe to newsletter"
>
<Button type="submit" variant="primary" size="md" aria-label="Subscribe to newsletter">
Submit
</button>
</Button>
</form>
</div>
</section>
Expand Down
17 changes: 11 additions & 6 deletions frontend/app/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React, { useEffect, useMemo, useRef, useState } from "react";
import clsx from "clsx";
import { Check, ChevronDown, Monitor, Moon, Sun } from "lucide-react";
import { Button } from '@/app/components/ui/Button';
import { type Theme, useTheme } from "../context/ThemeContext";

const themeOptions: Array<{
Expand Down Expand Up @@ -94,6 +95,7 @@ export default function ThemeToggle({

return (
<div ref={containerRef} className={clsx("relative", className)}>
<Button
<button
ref={triggerRef}
type="button"
Expand All @@ -104,8 +106,11 @@ export default function ThemeToggle({
aria-label={`Theme: ${activeOption.label}`}
aria-haspopup="menu"
aria-expanded={isOpen}
variant="ghost"
size={compact ? "sm" : "md"}
className={clsx(
"inline-flex items-center rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-text)] shadow-sm hover:border-[var(--color-border-strong)] hover:bg-[var(--color-surface-strong)] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--color-accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
"inline-flex items-center",
"shadow-sm hover:border-[var(--color-border-strong)] hover:bg-[var(--color-surface-strong)] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--color-accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
compact
? "h-10 w-10 justify-center"
: "gap-2 px-3.5 py-2.5 text-sm font-medium",
Expand Down Expand Up @@ -143,7 +148,7 @@ export default function ThemeToggle({
const selected = theme === value;

return (
<button
<Button
key={value}
type="button"
role="menuitemradio"
Expand All @@ -154,11 +159,11 @@ export default function ThemeToggle({
setIsOpen(false);
triggerRef.current?.focus();
}}
variant={selected ? "secondary" : "ghost"}
size="md"
className={clsx(
"flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--color-accent)] focus-visible:ring-inset",
selected
? "bg-[var(--color-accent-soft)] text-[var(--color-text)]"
: "text-[var(--color-text)] hover:bg-[var(--color-surface-subtle)]"
"flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left transition-colors focus-visible:ring-inset",
selected ? "bg-[var(--color-accent-soft)] text-[var(--color-text)]" : "text-[var(--color-text)] hover:bg-[var(--color-surface-subtle)]"
)}
>
<span className="flex h-9 w-9 items-center justify-center rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] text-[var(--color-accent)]">
Expand Down
40 changes: 40 additions & 0 deletions frontend/app/components/WalletReconnectBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use client";

import React from "react";
import { WifiOff, RefreshCw } from "lucide-react";
import { useWallet } from "../context/WalletContext";
import { Button } from "./ui/Button";

export function WalletReconnectBanner() {
const { connectionStatus, reconnect, isLoading } = useWallet();

if (connectionStatus !== "locked" && connectionStatus !== "disconnected") return null;

const isLocked = connectionStatus === "locked";

return (
<div
role="alert"
className="flex items-center justify-between gap-3 px-4 py-2.5 bg-amber-500/10 border-b border-amber-500/20 text-amber-200 text-sm"
>
<div className="flex items-center gap-2">
<WifiOff size={15} className="shrink-0" />
<span>
{isLocked
? "Your wallet was locked. Reconnect to continue."
: "Wallet disconnected. Reconnect to restore your session."}
</span>
</div>
<Button
variant="outline"
size="sm"
leftIcon={<RefreshCw size={13} />}
loading={isLoading}
onClick={reconnect}
className="border-amber-500/40 text-amber-200 hover:bg-amber-500/10 shrink-0"
>
Reconnect
</Button>
</div>
);
}
8 changes: 6 additions & 2 deletions frontend/app/components/dashboard/ContractDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React from "react";
import { Copy, FileCode, Calendar } from "lucide-react";
import { Button } from '@/app/components/ui/Button';

export type RiskLevel = "Low Risk" | "Medium Risk" | "High Risk";

Expand Down Expand Up @@ -108,17 +109,20 @@ const ContractDetailsCard: React.FC<ContractDetailsCardProps> = ({
<code className="text-cyan-400 font-mono text-sm flex-1 truncate">
{truncateAddress(contract.contractId, 8)}
</code>
<button
<Button
variant="ghost"
size="sm"
onClick={handleCopyContractId}
className="p-2 hover:bg-white/5 rounded-lg transition-colors duration-200"
title="Copy contract ID"
aria-label="Copy contract ID"
>
<Copy
className={`w-4 h-4 transition-colors duration-200 ${
copied ? "text-emerald-400" : "text-[#7a9fa9]"
}`}
/>
</button>
</Button>
</div>
{copied && (
<p className="text-emerald-400 text-xs mt-2">Copied to clipboard</p>
Expand Down
7 changes: 7 additions & 0 deletions frontend/app/components/dashboard/FeaturedGoalCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Plane, Calendar, ChevronRight } from 'lucide-react';
import { Button } from "../ui/Button";
import CircularProgress from './CircularProgress';
import Button from '../ui/Button';

Expand Down Expand Up @@ -83,6 +84,12 @@ const FeaturedGoalCard: React.FC<FeaturedGoalCardProps> = ({
</div>

<div className="flex items-center gap-4 mt-2">
<Button variant="primary" size="md" className="flex-1 md:flex-none px-6 py-3.5 bg-cyan-500 hover:bg-cyan-400 text-[#061a1a] font-bold rounded-2xl transition-all duration-300 shadow-[0_10px_20px_rgba(0,212,192,0.2)] hover:shadow-[0_15px_30px_rgba(0,212,192,0.4)] active:scale-95">
Contribute Now
</Button>
<Button variant="ghost" size="sm" className="flex items-center gap-1 text-cyan-400 font-bold hover:text-cyan-300 transition-colors px-2">
View Details
<ChevronRight size={18} className="transition-transform group-hover:translate-x-1" />
<Button variant="primary" size="lg" className="flex-1 md:flex-none">
Contribute Now
</Button>
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/components/dashboard/GoalCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import { Button } from '@/app/components/ui/Button';
import Link from "next/link";
import { Calendar, ChevronRight } from "lucide-react";
import Button from "../ui/Button";
Expand Down Expand Up @@ -112,6 +113,7 @@ export default function GoalCard({
</div>

<div className="flex items-center justify-between gap-3">
<Button className="px-4 py-2.5 rounded-2xl shadow-[0_10px_18px_rgba(0,212,192,0.15)]" variant="primary" size="md">
<Button variant="primary" size="sm">
Contribute
</Button>
Expand Down
9 changes: 9 additions & 0 deletions frontend/app/components/dashboard/GoalOverviewCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import React from "react";
import { Button } from "../ui/Button";
import {
Shield,
Calendar,
Expand Down Expand Up @@ -220,6 +221,14 @@ const GoalOverviewCard: React.FC<GoalOverviewCardProps> = ({

{/* ── Action buttons ── */}
<div className="mt-8 flex flex-wrap gap-3">
<Button onClick={onEditGoal} variant="outline" size="md" className="flex items-center gap-2 px-6 py-3 rounded-xl border border-white/10 bg-white/[0.04] hover:bg-white/[0.08] text-white font-semibold text-sm">
<Edit3 size={16} />
Edit Goal
</Button>
<Button onClick={onAddFunds} variant="primary" size="md" className="flex items-center gap-2 px-6 py-3 rounded-xl bg-cyan-500 hover:bg-cyan-400 text-[#061a1a] font-bold text-sm shadow-[0_8px_20px_rgba(0,212,192,0.2)] hover:shadow-[0_12px_28px_rgba(0,212,192,0.35)]">
<PlusCircle size={16} />
Add Funds
</Button>
<Button
variant="ghost"
size="md"
Expand Down
38 changes: 18 additions & 20 deletions frontend/app/components/dashboard/NetworkSwitchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React, { useRef } from "react";
import { X, ExternalLink, AlertTriangle, Shield } from "lucide-react";
import { Button } from '@/app/components/ui/Button';
import { getNetworkConfig } from "../../constants/networks";
import { useFocusTrap } from "../../hooks/useFocusTrap";
import { useToast } from "../../context/ToastContext";
Expand Down Expand Up @@ -121,15 +122,17 @@ const NetworkSwitchModal: React.FC<NetworkSwitchModalProps> = ({
</p>
</div>
</div>
<button
<Button
ref={closeButtonRef}
onClick={onClose}
aria-label="Close modal"
className="flex items-center justify-center text-slate-400 hover:text-white transition-colors bg-white/5 border border-white/10 rounded-lg cursor-pointer"
variant="ghost"
size="sm"
className="flex items-center justify-center text-slate-400 hover:text-white transition-colors bg-white/5 border border-white/10 rounded-lg"
style={{ width: 32, height: 32 }}
>
<X size={16} />
</button>
</Button>
</div>

{/* Modal Content - Scrollable */}
Expand Down Expand Up @@ -252,29 +255,24 @@ const NetworkSwitchModal: React.FC<NetworkSwitchModalProps> = ({

{/* Modal Footer - Action Buttons */}
<div className="flex gap-3 p-6 pt-4 border-t border-white/5">
<button
<Button
variant="secondary"
size="md"
className="flex-1 py-2.5 rounded-xl bg-white/5 border border-white/10 text-slate-300 text-sm font-medium hover:bg-white/10 transition-colors"
onClick={onClose}
className="flex-1 py-2.5 rounded-xl bg-white/5 border border-white/10 text-slate-300 text-sm font-medium hover:bg-white/10 transition-colors cursor-pointer"
>
Close
</button>
<button
</Button>
<Button
variant="primary"
size="md"
className="flex-1 py-2.5 rounded-xl text-sm font-semibold transition-colors flex items-center justify-center gap-2"
style={{ backgroundColor: "#08c1c1", color: "#021515" }}
onClick={handleOpenFreighter}
className="flex-1 py-2.5 rounded-xl text-sm font-semibold transition-colors cursor-pointer flex items-center justify-center gap-2"
style={{
backgroundColor: "#08c1c1",
color: "#021515",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = "#0fa3a3";
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "#08c1c1";
}}
leftIcon={<ExternalLink size={14} />}
>
Open Freighter
<ExternalLink size={14} />
</button>
</Button>
</div>
</div>
</div>
Expand Down
Loading