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
22 changes: 21 additions & 1 deletion app/test/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@ import LaunchCampaignFlow from '@/components/project/LaunchCampaignFlow';
import BoundlessSheet from '@/components/sheet/boundless-sheet';
import { Button } from '@/components/ui/button';
import { Rocket } from 'lucide-react';
import { useWalletProtection } from '@/hooks/use-wallet-protection';
import WalletRequiredModal from '@/components/wallet/WalletRequiredModal';

export default function TestPage() {
const [showLaunchFlow, setShowLaunchFlow] = useState(false);

// Wallet protection hook
const {
requireWallet,
showWalletModal,
handleWalletConnected,
closeWalletModal,
} = useWalletProtection({
actionName: 'test launch campaign',
});

const handleOpenModal = () => {
setShowLaunchFlow(true);
requireWallet(() => setShowLaunchFlow(true));
};

const handleCloseModal = () => {
Expand Down Expand Up @@ -55,6 +67,14 @@ export default function TestPage() {
onComplete={handleCloseModal}
/>
</BoundlessSheet>

{/* Wallet Required Modal */}
<WalletRequiredModal
open={showWalletModal}
onOpenChange={closeWalletModal}
actionName='test launch campaign'
onWalletConnected={handleWalletConnected}
/>
</div>
</div>
);
Expand Down
110 changes: 0 additions & 110 deletions app/user/backing-history/page.tsx

This file was deleted.

9 changes: 2 additions & 7 deletions app/user/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { Coins, History } from 'lucide-react';
import { useAuth } from '@/hooks/use-auth';
import CampaignTable from '@/components/campaigns/CampaignTable';
import { useEffect, useState } from 'react';

import LoadingSpinner from '@/components/LoadingSpinner';
import { UserPageSkeleton } from '@/components/skeleton/UserPageSkeleton';

export default function UserPage() {
const { user, isLoading } = useAuth();
Expand All @@ -20,11 +19,7 @@ export default function UserPage() {

// Show loading until client-side hydration is complete
if (!mounted || isLoading) {
return (
<div className='min-h-screen flex items-center justify-center'>
<LoadingSpinner size='lg' />
</div>
);
return <UserPageSkeleton />;
}

return (
Expand Down
24 changes: 17 additions & 7 deletions app/user/projects/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
'use client';
import PageTransition from '@/components/PageTransition';
import Projects from '@/components/Projects';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { ProjectsPageSkeleton } from '@/components/skeleton/ProjectsSkeleton';

const Page = () => {
const [mounted, setMounted] = useState(false);

useEffect(() => {
setMounted(true);
}, []);

// Show loading until client-side hydration is complete
if (!mounted) {
return <ProjectsPageSkeleton />;
}

const page = () => {
return (
<PageTransition>
<div className='min-h-screen'>
<div className='p-4 sm:p-6 lg:p-8 max-w-7xl mx-auto'>
{/* <div className='bg-[#1C1C1C] p-4 sm:p-6 mx-6 rounded-[12px] flex flex-col gap-6 sm:gap-8 '> */}
<Projects />
{/* </div> */}
<Projects />
</div>
</div>
</PageTransition >
</PageTransition>
);
};

export default page;
export default Page;
29 changes: 16 additions & 13 deletions components/Projects.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import React, { useState, useEffect, useCallback } from 'react';
import { RecentProjectsProps } from '@/types/project';
import { Plus, ChevronDown, Loader2 } from 'lucide-react';
import { Plus, ChevronDown } from 'lucide-react';
import ProjectCard from './project-card';
import EmptyState from './EmptyState';
import { BoundlessButton } from './buttons';
Expand All @@ -20,6 +20,7 @@ import { getProjects } from '@/lib/api/project';
import { toast } from 'sonner';
import { useAuth } from '@/hooks/use-auth';
import { useProjectSheetStore } from '@/lib/stores/project-sheet-store';
import { ProjectsSkeleton } from './skeleton/ProjectsSkeleton';

type StatusFilter =
| 'all'
Expand Down Expand Up @@ -93,6 +94,19 @@ const Projects = () => {
fetchProjects();
}, [fetchProjects]);

if (loading) {
return (
<motion.div
className='bg-[#1C1C1C] p-4 sm:p-6 rounded-[12px] flex flex-col gap-6 sm:gap-8 w-full'
initial='hidden'
animate='visible'
variants={fadeInUp}
>
<ProjectsSkeleton />
</motion.div>
);
}

return (
<motion.div
className='bg-[#1C1C1C] p-4 sm:p-6 rounded-[12px] flex flex-col gap-6 sm:gap-8 w-full'
Expand All @@ -108,7 +122,6 @@ const Projects = () => {
<h2 className='text-white text-base sm:text-lg xl:text-xl font-semibold leading-[120%] tracking-[-0.4px]'>
{tabFilter === 'mine' ? 'My Projects' : 'All Projects'}
</h2>

</div>
<div className='flex flex-col sm:flex-row items-start sm:items-center gap-2 sm:gap-3 w-full xl:w-auto'>
<Tabs
Expand Down Expand Up @@ -180,16 +193,7 @@ const Projects = () => {
className='grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols- xl:grid-cols-3 gap-4 sm:gap-6'
variants={staggerContainer}
>
{loading ? (
<motion.div className='col-span-full' variants={fadeInUp}>
<div className='flex items-center justify-center py-12'>
<div className='flex items-center gap-3'>
<Loader2 className='w-6 h-6 animate-spin text-[#1671D9]' />
<span className='text-[#B5B5B5]'>Loading projects...</span>
</div>
</div>
</motion.div>
) : error ? (
{error ? (
<motion.div className='col-span-full' variants={fadeInUp}>
<div className='flex items-center justify-center py-12'>
<div className='text-center'>
Expand Down Expand Up @@ -268,7 +272,6 @@ const Projects = () => {
iconPosition='right'
onClick={() => {
sheet.openInitialize();

}}
>
New Project.
Expand Down
1 change: 1 addition & 0 deletions components/auth/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const LoginForm = () => {
'Login successful but session not found. Please try again.',
});
}
router.push(callbackUrl);
} else {
form.setError('root', {
type: 'manual',
Expand Down
27 changes: 12 additions & 15 deletions components/campaigns/CampaignTable.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import { Button } from '../ui/button';
import {
MoreVerticalIcon,
CheckIcon,
ChevronDownIcon,
Loader2Icon,
} from 'lucide-react';
import { MoreVerticalIcon, CheckIcon, ChevronDown } from 'lucide-react';
import { Tabs, TabsList, TabsTrigger } from '../ui/tabs';
import {
DropdownMenu,
Expand All @@ -27,6 +22,7 @@ import {
} from '@/lib/data/campaigns-mock';
import BackingHistory from './backing-history';
import { sampleBackers } from '@/lib/data/backing-history-mock';
import { CampaignTableSkeleton } from '../skeleton/UserPageSkeleton';

const CampaignRow = ({
campaign,
Expand Down Expand Up @@ -518,6 +514,14 @@ const CampaignTable = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};

if (loading) {
return (
<div className='space-y-6 min-h-full'>
<CampaignTableSkeleton />
</div>
);
}

return (
<div className='space-y-6 min-h-full'>
<div className='flex flex-col xl:flex-row justify-between items-start xl:items-center gap-3 sm:gap-4 xl:gap-0'>
Expand Down Expand Up @@ -566,7 +570,7 @@ const CampaignTable = () => {
filterOptions.find(option => option.value === statusFilter)
?.label
}{' '}
<ChevronDownIcon className='w-3 h-3 sm:w-4 sm:h-4' />
<ChevronDown className='w-3 h-3 sm:w-4 sm:h-4' />
</BoundlessButton>
</DropdownMenuTrigger>
<DropdownMenuContent
Expand Down Expand Up @@ -602,14 +606,7 @@ const CampaignTable = () => {
</div>

<div className='space-y-3'>
{loading ? (
<div className='flex items-center justify-center py-12'>
<div className='flex items-center gap-3'>
<Loader2Icon className='w-6 h-6 animate-spin text-[#1671D9]' />
<span className='text-[#B5B5B5]'>Loading campaigns...</span>
</div>
</div>
) : error ? (
{error ? (
<div className='flex items-center justify-center py-12'>
<div className='text-center'>
<p className='text-red-400 mb-2'>{error}</p>
Expand Down
22 changes: 21 additions & 1 deletion components/campaigns/LaunchCampaignFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
} from '@/components/ui/select';
import { BoundlessButton } from '../buttons';
import { Checkbox } from '../ui/checkbox';
import { useWalletProtection } from '@/hooks/use-wallet-protection';
import WalletRequiredModal from '@/components/wallet/WalletRequiredModal';

interface LaunchCampaignFlowProps {
onComplete: () => void;
Expand Down Expand Up @@ -60,6 +62,16 @@ const LaunchCampaignFlow: React.FC<LaunchCampaignFlowProps> = ({
const [currentPhase, setCurrentPhase] = useState<'details' | 'escrow'>(
'details'
);

// Wallet protection hook
const {
requireWallet,
showWalletModal,
handleWalletConnected,
closeWalletModal,
} = useWalletProtection({
actionName: 'launch campaign',
});
const [formData, setFormData] = useState({
title: 'Boundless',
description:
Expand Down Expand Up @@ -280,9 +292,17 @@ const LaunchCampaignFlow: React.FC<LaunchCampaignFlowProps> = ({
escrowTerms={escrowTerms}
isEscrowValid={isEscrowValid}
onBack={handleBackPhase}
onComplete={onComplete}
onComplete={() => requireWallet(onComplete)}
/>
)}

{/* Wallet Required Modal */}
<WalletRequiredModal
open={showWalletModal}
onOpenChange={closeWalletModal}
actionName='launch campaign'
onWalletConnected={handleWalletConnected}
/>
</div>
);
};
Expand Down
Loading
Loading