From 6eeae28378e164d5573c7cc40bb09bf1f8a1984a Mon Sep 17 00:00:00 2001 From: Manus AI Date: Tue, 20 Jan 2026 01:20:40 -0500 Subject: [PATCH 1/4] Integrate billing popup, usage sidebar, and credit preview toggle --- bun.lock | 1 + components/header.tsx | 31 ++++-- components/purchase-credits-popup.tsx | 57 +++++++++++ components/sidebar/chat-history-client.tsx | 30 ++++++ components/usage-sidebar.tsx | 113 +++++++++++++++++++++ 5 files changed, 222 insertions(+), 10 deletions(-) create mode 100644 components/purchase-credits-popup.tsx create mode 100644 components/usage-sidebar.tsx diff --git a/bun.lock b/bun.lock index 936916d2..59ccf04f 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "QCX", diff --git a/components/header.tsx b/components/header.tsx index 644ba8c0..71c7556c 100644 --- a/components/header.tsx +++ b/components/header.tsx @@ -15,10 +15,24 @@ import { } from 'lucide-react' import { MapToggle } from './map-toggle' import { ProfileToggle } from './profile-toggle' +import { PurchaseCreditsPopup } from './purchase-credits-popup' +import { UsageSidebar } from './usage-sidebar' +import { useState, useEffect } from 'react' export const Header = () => { const { toggleCalendar } = useCalendarToggle() + const [isPurchaseOpen, setIsPurchaseOpen] = useState(false) + const [isUsageOpen, setIsUsageOpen] = useState(false) + + useEffect(() => { + // Open payment popup as soon as application opens + setIsPurchaseOpen(true) + }, []) + return ( + <> + setIsPurchaseOpen(false)} /> + setIsUsageOpen(false)} />
@@ -53,11 +67,9 @@ export const Header = () => {
- - - + @@ -67,14 +79,13 @@ export const Header = () => { {/* Mobile menu buttons */}
- - - +
+ ) } diff --git a/components/purchase-credits-popup.tsx b/components/purchase-credits-popup.tsx new file mode 100644 index 00000000..63a4b83c --- /dev/null +++ b/components/purchase-credits-popup.tsx @@ -0,0 +1,57 @@ +'use client'; + +import React from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { CreditCard, Zap } from 'lucide-react'; + +interface PurchaseCreditsPopupProps { + isOpen: boolean; + onClose: () => void; +} + +export function PurchaseCreditsPopup({ isOpen, onClose }: PurchaseCreditsPopupProps) { + const handlePurchase = () => { + window.open('https://buy.stripe.com/3cIaEX3tRcur9EM7tbasg00', '_blank'); + onClose(); + }; + + return ( + + + + + + Upgrade Your Plan + + + You've reached your credit limit. Upgrade now to continue using all features seamlessly. + + +
+
+
+

Standard Tier

+

Unlimited searches & more

+
+

$20/mo

+
+
+ + + + +
+
+ ); +} diff --git a/components/sidebar/chat-history-client.tsx b/components/sidebar/chat-history-client.tsx index 9190dea7..5af15a4e 100644 --- a/components/sidebar/chat-history-client.tsx +++ b/components/sidebar/chat-history-client.tsx @@ -18,6 +18,7 @@ import { } from '@/components/ui/alert-dialog'; import { toast } from 'sonner'; import { Spinner } from '@/components/ui/spinner'; +import { Zap, ChevronDown, ChevronUp } from 'lucide-react'; import HistoryItem from '@/components/history-item'; // Adjust path if HistoryItem is moved or renamed import type { Chat as DrizzleChat } from '@/lib/actions/chat-db'; // Use the Drizzle-based Chat type @@ -31,6 +32,7 @@ export function ChatHistoryClient({}: ChatHistoryClientProps) { const [error, setError] = useState(null); const [isClearPending, startClearTransition] = useTransition(); const [isAlertDialogOpen, setIsAlertDialogOpen] = useState(false); + const [isCreditsVisible, setIsCreditsVisible] = useState(false); const router = useRouter(); useEffect(() => { @@ -113,6 +115,34 @@ export function ChatHistoryClient({}: ChatHistoryClientProps) { return (
+
+ + + {isCreditsVisible && ( +
+
+ Available Credits + 0 +
+
+
+
+

Upgrade to get more credits

+
+ )} +
+
{!chats?.length ? (
diff --git a/components/usage-sidebar.tsx b/components/usage-sidebar.tsx new file mode 100644 index 00000000..4ce5ca8d --- /dev/null +++ b/components/usage-sidebar.tsx @@ -0,0 +1,113 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, +} from '@/components/ui/sheet'; +import { Button } from '@/components/ui/button'; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; +import { Zap, RefreshCw, LayoutPanelLeft, X } from 'lucide-react'; + +interface UsageSidebarProps { + isOpen: boolean; + onClose: () => void; +} + +export function UsageSidebar({ isOpen, onClose }: UsageSidebarProps) { + const [usage, setUsage] = useState([]); + const [credits, setCredits] = useState(0); + + useEffect(() => { + if (isOpen) { + // Mock data for now as per the screenshot + setUsage([ + { details: 'Efficiently Fix Pull Request ...', date: '2026-01-17 08:05', change: -418 }, + { details: 'Fix Build and Add Parallel S...', date: '2026-01-16 06:10', change: -482 }, + { details: 'How to Add a Feature to a ...', date: '2026-01-14 10:42', change: -300 }, + ]); + setCredits(0); + } + }, [isOpen]); + + return ( + + +
+
+

Usage

+ +
+ +
+
+ Free + +
+ +
+
+
+ + Credits +
+ {credits} +
+
+ Free credits + 0 +
+
+ +
+
+
+ + Daily refresh credits +
+ 300 +
+

Refresh to 300 at 00:00 every day

+
+
+ +
+
+
+ + Website usage & billing +
+ +
+ + + + + Details + Date + Credits change + + + + {usage.map((item, i) => ( + + {item.details} + {item.date} + {item.change} + + ))} + +
+
+
+
+
+ ); +} From 160e08243d1e0859c269c699623ff9e2bde720ab Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:20:55 +0000 Subject: [PATCH 2/4] Recover lost commit 488b47c and restore branch head Restored the branch to the expected head at commit 488b47c149de4dc764f4429753be6672526ff452. This recovers several missing features and architectural improvements: - Integrated HistoryToggleProvider and HistorySidebar. - Integrated UsageToggleProvider and the new UsageView component. - Removed legacy usage-sidebar.tsx. - Restored pricing and feature updates in PurchaseCreditsPopup. - Fixed layout structure in app/layout.tsx to support these new global state providers. Resolved previous merge conflicts and incorrect force-push state. Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> --- app/layout.tsx | 52 +++++++----- components/chat.tsx | 7 +- components/conditional-lottie.tsx | 6 +- components/header.tsx | 27 ++++-- components/history-sidebar.tsx | 35 ++++++++ components/history-toggle-context.tsx | 30 +++++++ components/history.tsx | 54 ++++-------- components/profile-toggle-context.tsx | 7 +- components/profile-toggle.tsx | 18 ++-- components/purchase-credits-popup.tsx | 26 ++++-- components/usage-sidebar.tsx | 113 -------------------------- components/usage-toggle-context.tsx | 30 +++++++ components/usage-view.tsx | 96 ++++++++++++++++++++++ 13 files changed, 304 insertions(+), 197 deletions(-) create mode 100644 components/history-sidebar.tsx create mode 100644 components/history-toggle-context.tsx delete mode 100644 components/usage-sidebar.tsx create mode 100644 components/usage-toggle-context.tsx create mode 100644 components/usage-view.tsx diff --git a/app/layout.tsx b/app/layout.tsx index a092d4fe..bddadc19 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -12,7 +12,10 @@ import { SpeedInsights } from "@vercel/speed-insights/next" import { Toaster } from '@/components/ui/sonner' import { MapToggleProvider } from '@/components/map-toggle-context' import { ProfileToggleProvider } from '@/components/profile-toggle-context' +import { UsageToggleProvider } from '@/components/usage-toggle-context' import { CalendarToggleProvider } from '@/components/calendar-toggle-context' +import { HistoryToggleProvider } from '@/components/history-toggle-context' +import { HistorySidebar } from '@/components/history-sidebar' import { MapLoadingProvider } from '@/components/map-loading-context'; import ConditionalLottie from '@/components/conditional-lottie'; import { MapProvider as MapContextProvider } from '@/components/map/map-context' @@ -70,28 +73,33 @@ export default function RootLayout({ )} > - - - - - -
- - {children} - -