diff --git a/frontend/src/app/(dashboard)/dashboard/page.tsx b/frontend/src/app/(dashboard)/dashboard/page.tsx index 59bbcb05..b29673ff 100644 --- a/frontend/src/app/(dashboard)/dashboard/page.tsx +++ b/frontend/src/app/(dashboard)/dashboard/page.tsx @@ -26,6 +26,7 @@ import { config } from '@/lib/config'; import { cn } from '@/lib/utils'; import { useInitiateAgentWithInvalidation } from '@/hooks/react-query/dashboard/use-initiate-agent'; import { ModalProviders } from '@/providers/modal-providers'; +import { useModal } from '@/hooks/use-modal-store'; const PENDING_PROMPT_KEY = 'pendingAgentPrompt'; @@ -42,6 +43,7 @@ function DashboardContent() { const personalAccount = accounts?.find((account) => account.personal_account); const chatInputRef = useRef(null); const initiateAgentMutation = useInitiateAgentWithInvalidation(); + const { onOpen } = useModal(); const secondaryGradient = 'bg-gradient-to-r from-blue-500 to-blue-500 bg-clip-text text-transparent'; @@ -96,17 +98,7 @@ function DashboardContent() { console.error('Error during submission process:', error); if (error instanceof BillingError) { console.log('Handling BillingError:', error.detail); - handleBillingError({ - message: - error.detail.message || - 'Monthly usage limit reached. Please upgrade your plan.', - currentUsage: error.detail.currentUsage as number | undefined, - limit: error.detail.limit as number | undefined, - subscription: error.detail.subscription || { - price_id: config.SUBSCRIPTION_TIERS.FREE.priceId, - plan_name: 'Free', - }, - }); + onOpen("paymentRequiredDialog"); } } finally { setIsSubmitting(false); diff --git a/frontend/src/app/(home)/page.tsx b/frontend/src/app/(home)/page.tsx index 3476d52d..08b6dcac 100644 --- a/frontend/src/app/(home)/page.tsx +++ b/frontend/src/app/(home)/page.tsx @@ -8,25 +8,29 @@ import { HeroSection } from '@/components/home/sections/hero-section'; import { OpenSourceSection } from '@/components/home/sections/open-source-section'; import { PricingSection } from '@/components/home/sections/pricing-section'; import { UseCasesSection } from '@/components/home/sections/use-cases-section'; +import { ModalProviders } from '@/providers/modal-providers'; export default function Home() { return ( -
-
- - - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - - - {/* */} - {/* */} - - -
-
+ <> + +
+
+ + + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + + + {/* */} + {/* */} + + +
+
+ ); } diff --git a/frontend/src/components/home/sections/hero-section.tsx b/frontend/src/components/home/sections/hero-section.tsx index 1601979a..1025834b 100644 --- a/frontend/src/components/home/sections/hero-section.tsx +++ b/frontend/src/components/home/sections/hero-section.tsx @@ -33,6 +33,7 @@ import { useBillingError } from '@/hooks/useBillingError'; import { useAccounts } from '@/hooks/use-accounts'; import { isLocalMode, config } from '@/lib/config'; import { toast } from 'sonner'; +import { useModal } from '@/hooks/use-modal-store'; // Custom dialog overlay with blur effect const BlurredDialogOverlay = () => ( @@ -57,6 +58,7 @@ export function HeroSection() { useBillingError(); const { data: accounts } = useAccounts(); const personalAccount = accounts?.find((account) => account.personal_account); + const { onOpen } = useModal(); // Auth dialog state const [authDialogOpen, setAuthDialogOpen] = useState(false); @@ -142,17 +144,8 @@ export function HeroSection() { // Check specifically for BillingError (402) if (error instanceof BillingError) { console.log('Handling BillingError from hero section:', error.detail); - handleBillingError({ - message: - error.detail.message || - 'Monthly usage limit reached. Please upgrade your plan.', - currentUsage: error.detail.currentUsage as number | undefined, - limit: error.detail.limit as number | undefined, - subscription: error.detail.subscription || { - price_id: config.SUBSCRIPTION_TIERS.FREE.priceId, // Default Free - plan_name: 'Free', - }, - }); + // Open the payment required dialog modal instead of showing the alert + onOpen("paymentRequiredDialog"); // Don't show toast for billing errors } else { // Handle other errors (e.g., network, other API errors) diff --git a/frontend/src/hooks/react-query/dashboard/use-initiate-agent.ts b/frontend/src/hooks/react-query/dashboard/use-initiate-agent.ts index e0a2251d..7885bd64 100644 --- a/frontend/src/hooks/react-query/dashboard/use-initiate-agent.ts +++ b/frontend/src/hooks/react-query/dashboard/use-initiate-agent.ts @@ -18,12 +18,16 @@ export const useInitiateAgentMutation = createMutationHook< }, onError: (error) => { if (error instanceof Error) { - if (error.message.includes("Cannot connect to backend server")) { + const errorMessage = error.message; + if (errorMessage.toLowerCase().includes("payment required")) { + return; + } + if (errorMessage.includes("Cannot connect to backend server")) { toast.error("Connection error: Please check your internet connection and ensure the backend server is running"); - } else if (error.message.includes("No access token available")) { + } else if (errorMessage.includes("No access token available")) { toast.error("Authentication error: Please sign in again"); } else { - toast.error(`Failed to initiate agent: ${error.message}`); + toast.error(`Failed to initiate agent: ${errorMessage}`); } } else { toast.error("An unexpected error occurred while initiating the agent"); @@ -40,8 +44,14 @@ export const useInitiateAgentWithInvalidation = () => { queryClient.invalidateQueries({ queryKey: dashboardKeys.agents }); }, onError: (error) => { - if (error instanceof Error && error.message.includes("Payment Required")) { - onOpen("paymentRequiredDialog"); + console.log('Mutation error:', error); + if (error instanceof Error) { + const errorMessage = error.message; + if (errorMessage.toLowerCase().includes("payment required")) { + console.log('Opening payment required modal'); + onOpen("paymentRequiredDialog"); + return; + } } } }); diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 8c618c39..ca51b463 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1423,7 +1423,6 @@ export const initiateAgent = async ( throw new Error('No access token available'); } - // Check if backend URL is configured if (!API_URL) { throw new Error( 'Backend URL is not configured. Set NEXT_PUBLIC_BACKEND_URL in your environment.', @@ -1447,10 +1446,20 @@ export const initiateAgent = async ( const errorText = await response .text() .catch(() => 'No error details available'); + console.error( `[API] Error initiating agent: ${response.status} ${response.statusText}`, errorText, ); + + if (response.status === 402) { + throw new Error('Payment Required'); + } else if (response.status === 401) { + throw new Error('Authentication error: Please sign in again'); + } else if (response.status >= 500) { + throw new Error('Server error: Please try again later'); + } + throw new Error( `Error initiating agent: ${response.statusText} (${response.status})`, ); @@ -1460,7 +1469,6 @@ export const initiateAgent = async ( } catch (error) { console.error('[API] Failed to initiate agent:', error); - // Provide clearer error message for network errors if ( error instanceof TypeError && error.message.includes('Failed to fetch')