Skip to content
Open
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
82 changes: 58 additions & 24 deletions backend/frontend/app/auth/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
'use client';

import { motion } from 'framer-motion';
import { SocialLogin } from '@/components/auth/SocialLogin';
import { WalletConnect } from '@/components/auth/WalletConnect';
import dynamic from 'next/dynamic';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Wallet, Users } from 'lucide-react';
import { Skeleton } from '@/components/ui/skeleton';
// DashboardProviders must be a static import so WagmiProvider is available
// synchronously before any child component calls useAccount() or useConnect().
// Dynamically importing it would cause a race where WalletConnect renders
// before the provider mounts, throwing a wagmi context error.
import { DashboardProviders } from '@/components/providers-dashboard';

// Dynamically import the heavy auth components — they pull in @web3auth/modal
// and wagmi connectors. Loading them on-demand keeps the auth page's initial
// JS small while the provider is already in place.
const SocialLogin = dynamic(
() => import('@/components/auth/SocialLogin').then((m) => m.SocialLogin),
{
loading: () => (
<div className="space-y-3 mt-6">
{[1, 2, 3].map((i) => (
<Skeleton key={i} className="h-12 w-full rounded-md" />
))}
</div>
),
ssr: false,
}
);

const WalletConnect = dynamic(
() => import('@/components/auth/WalletConnect').then((m) => m.WalletConnect),
{
loading: () => (
<div className="space-y-3 mt-6">
<Skeleton className="h-12 w-full rounded-md" />
</div>
),
ssr: false,
}
);

export default function AuthPage() {
return (
Expand All @@ -28,31 +62,32 @@ export default function AuthPage() {
<h1 className="text-3xl font-bold text-gray-900 mb-2">
Welcome to AgenticPay
</h1>
<p className="text-gray-600">
Get paid instantly for your work
</p>
<p className="text-gray-600">Get paid instantly for your work</p>
</div>

<Tabs defaultValue="social" className="w-full">
<TabsList className="grid w-full grid-cols-2 mb-6">
<TabsTrigger value="social" className="flex items-center gap-2">
<Users className="h-4 w-4" />
Social Login
</TabsTrigger>
<TabsTrigger value="wallet" className="flex items-center gap-2">
<Wallet className="h-4 w-4" />
Web3 Wallet
</TabsTrigger>
</TabsList>
{/* Provider must wrap the tabs so WalletConnect can call useConnect() */}
<DashboardProviders>
<Tabs defaultValue="social" className="w-full">
<TabsList className="grid w-full grid-cols-2 mb-6">
<TabsTrigger value="social" className="flex items-center gap-2">
<Users className="h-4 w-4" />
Social Login
</TabsTrigger>
<TabsTrigger value="wallet" className="flex items-center gap-2">
<Wallet className="h-4 w-4" />
Web3 Wallet
</TabsTrigger>
</TabsList>

<TabsContent value="social">
<SocialLogin />
</TabsContent>
<TabsContent value="social">
<SocialLogin />
</TabsContent>

<TabsContent value="wallet">
<WalletConnect />
</TabsContent>
</Tabs>
<TabsContent value="wallet">
<WalletConnect />
</TabsContent>
</Tabs>
</DashboardProviders>

<p className="text-xs text-gray-500 text-center mt-6">
By continuing, you agree to our Terms of Service and Privacy Policy
Expand All @@ -62,4 +97,3 @@ export default function AuthPage() {
</div>
);
}

13 changes: 4 additions & 9 deletions backend/frontend/app/dashboard/invoices/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use client';

import { useState } from 'react';
import { useDashboardData, DashboardInvoice } from '@/lib/hooks/useDashboardData';
import { useDashboardData } from '@/lib/hooks/useDashboardData';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { CheckCircle2, Clock, AlertCircle, Filter, FileText } from 'lucide-react';
import { motion } from 'framer-motion';
import { FadeIn } from '@/components/ui/fade-in';
import Link from 'next/link';
import { InvoiceCardSkeleton } from '@/components/ui/loading-skeletons';
import { EmptyState } from '@/components/empty/EmptyState';
Expand Down Expand Up @@ -88,12 +88,7 @@ export default function InvoicesPage() {

<div className="grid grid-cols-1 gap-4">
{filteredInvoices.map((invoice, index) => (
<motion.div
key={invoice.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.05 }}
>
<FadeIn key={invoice.id} delay={index * 0.05}>
<Link href={`/dashboard/projects/${invoice.projectId}`}>
<Card className="hover:shadow-lg transition-all cursor-pointer">
<CardContent className="p-6">
Expand Down Expand Up @@ -124,7 +119,7 @@ export default function InvoicesPage() {
</CardContent>
</Card>
</Link>
</motion.div>
</FadeIn>
))}
</div>

Expand Down
44 changes: 31 additions & 13 deletions backend/frontend/app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@
import { useAuthStore } from '@/store/useAuthStore';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { Sidebar } from '@/components/layout/Sidebar';
import { Header } from '@/components/layout/Header';
import dynamic from 'next/dynamic';
import { DashboardProviders } from '@/components/providers-dashboard';
import { ErrorBoundary } from '@/components/errors/ErrorBoundary';

// Sidebar and Header are dashboard-only — load them as part of the dashboard
// chunk rather than the root bundle.
const Sidebar = dynamic(
() => import('@/components/layout/Sidebar').then((m) => m.Sidebar),
{ ssr: false }
);
const Header = dynamic(
() => import('@/components/layout/Header').then((m) => m.Header),
{ ssr: false }
);

// PWA components are non-critical — load after the dashboard is interactive.
const PWAWrapper = dynamic(() => import('@/components/PWAWrapper'), {
ssr: false,
});

export default function DashboardLayout({
children,
}: {
Expand All @@ -26,17 +42,19 @@ export default function DashboardLayout({
}

return (
<ErrorBoundary>
<div className="flex h-screen bg-gray-50">
<Sidebar />
<div className="flex-1 flex flex-col overflow-hidden lg:ml-64">
<Header />
<main className="flex-1 overflow-y-auto p-4 sm:p-6">
<ErrorBoundary>{children}</ErrorBoundary>
</main>
<DashboardProviders>
<ErrorBoundary>
<div className="flex h-screen bg-gray-50">
<Sidebar />
<div className="flex-1 flex flex-col overflow-hidden lg:ml-64">
<Header />
<main className="flex-1 overflow-y-auto p-4 sm:p-6">
<ErrorBoundary>{children}</ErrorBoundary>
</main>
</div>
</div>
</div>
</ErrorBoundary>
<PWAWrapper />
</ErrorBoundary>
</DashboardProviders>
);
}

42 changes: 11 additions & 31 deletions backend/frontend/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useDashboardData } from '@/lib/hooks/useDashboardData';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DollarSign, Clock, Folder, CheckCircle2, TrendingUp } from 'lucide-react';
import { motion } from 'framer-motion';
import { FadeIn } from '@/components/ui/fade-in';
import { DashboardStatsSkeleton } from '@/components/ui/loading-skeletons';

export default function DashboardPage() {
Expand Down Expand Up @@ -43,11 +43,7 @@ export default function DashboardPage() {

{/* Stats Grid */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1 }}
>
<FadeIn delay={0.1}>
<Card className="hover:shadow-lg transition-shadow">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium text-gray-600">
Expand All @@ -63,13 +59,9 @@ export default function DashboardPage() {
</p>
</CardContent>
</Card>
</motion.div>
</FadeIn>

<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
>
<FadeIn delay={0.2}>
<Card className="hover:shadow-lg transition-shadow">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium text-gray-600">
Expand All @@ -82,13 +74,9 @@ export default function DashboardPage() {
<p className="text-xs text-yellow-600 mt-1">Awaiting approval</p>
</CardContent>
</Card>
</motion.div>
</FadeIn>

<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
>
<FadeIn delay={0.3}>
<Card className="hover:shadow-lg transition-shadow">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium text-gray-600">
Expand All @@ -101,13 +89,9 @@ export default function DashboardPage() {
<p className="text-xs text-blue-600 mt-1">In progress</p>
</CardContent>
</Card>
</motion.div>
</FadeIn>

<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
>
<FadeIn delay={0.4}>
<Card className="hover:shadow-lg transition-shadow">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium text-gray-600">
Expand All @@ -120,15 +104,11 @@ export default function DashboardPage() {
<p className="text-xs text-gray-600 mt-1">Projects done</p>
</CardContent>
</Card>
</motion.div>
</FadeIn>
</div>

{/* Recent Activity */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
>
<FadeIn delay={0.5}>
<Card>
<CardHeader>
<CardTitle>Recent Activity</CardTitle>
Expand All @@ -152,7 +132,7 @@ export default function DashboardPage() {
)}
</CardContent>
</Card>
</motion.div>
</FadeIn>
</div>
);
}
Expand Down
11 changes: 3 additions & 8 deletions backend/frontend/app/dashboard/payments/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useDashboardData } from '@/lib/hooks/useDashboardData';
import { Card, CardContent } from '@/components/ui/card';
import { CheckCircle2, Clock, XCircle, ExternalLink, Wallet } from 'lucide-react';
import { motion } from 'framer-motion';
import { FadeIn } from '@/components/ui/fade-in';
import { PaymentCardSkeleton } from '@/components/ui/loading-skeletons';
import { EmptyState } from '@/components/empty/EmptyState';

Expand Down Expand Up @@ -48,12 +48,7 @@ export default function PaymentsPage() {

<div className="space-y-4">
{payments.map((payment, index) => (
<motion.div
key={payment.id}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.05 }}
>
<FadeIn key={payment.id} delay={index * 0.05}>
<Card className="hover:shadow-lg transition-all">
<CardContent className="p-6">
<div className="flex items-center justify-between">
Expand Down Expand Up @@ -95,7 +90,7 @@ export default function PaymentsPage() {
)}
</CardContent>
</Card>
</motion.div>
</FadeIn>
))}
</div>

Expand Down
Loading