+ {days.map((d, i) => (
+
0 ? 8 : 2)}%` }}
+ title={`${d.date}: ${d.count} conversations`}
+ />
+ ))}
+
+ )
+}
+
+// ─── Stat card ────────────────────────────────────────────────────────────────
+const StatCard: React.FC<{
+ label: string
+ value: string | number
+ icon: React.ReactNode
+ subtitle?: string
+ color?: string
+}> = ({ label, value, icon, subtitle, color = 'primary' }) => (
+
+
+ {typeof value === 'number' ? value.toLocaleString() : value}
+ {subtitle && {subtitle}
}
+
+)
+
+// ─── Usage bar ────────────────────────────────────────────────────────────────
+const UsageBar: React.FC<{ used: number; limit: number }> = ({ used, limit }) => {
+ const pct = limit > 0 ? Math.min((used / limit) * 100, 100) : 0
+ const isHigh = pct > 80
+ const isFull = pct >= 100
+
+ return (
+
+
+ Monthly conversations
+
+ {used.toLocaleString()} / {limit.toLocaleString()}
+
+
+
+
+ )
+}
+
+// ─── Chatbot detail row ───────────────────────────────────────────────────────
+const ChatbotRow: React.FC<{ chatbot: ChatbotAnalytics }> = ({ chatbot }) => {
+ const [expanded, setExpanded] = useState(false)
+
+ return (
+
+
+
+ {expanded && (
+
+ {/* Stats row */}
+
+
+
Today
+
{chatbot.conversations_today}
+
+
+
This week
+
{chatbot.conversations_this_week}
+
+
+
This month
+
{chatbot.conversations_this_month}
+
+
+
Avg messages/convo
+
{chatbot.average_messages_per_conversation}
+
+
+
+ {/* Daily chart */}
+
+
+ {/* Top queries & Languages side by side */}
+
+ {chatbot.top_queries.length > 0 && (
+
+
Top questions
+
+ {chatbot.top_queries.slice(0, 5).map((q, i) => (
+ -
+ {i + 1}.
+ {q.query}
+ {q.count}×
+
+ ))}
+
+
+ )}
+
+ {Object.keys(chatbot.languages_used).length > 0 && (
+
+
Languages
+
+ {Object.entries(chatbot.languages_used)
+ .sort(([, a], [, b]) => b - a)
+ .slice(0, 5)
+ .map(([lang, count]) => (
+
+
+ {lang}
+ {count} convos
+
+ ))}
+
+
+ )}
+
+
+ {chatbot.peak_hour !== null && (
+
+
+ Peak hour: {chatbot.peak_hour}:00 - {chatbot.peak_hour + 1}:00
+
+ )}
+
+ )}
+
+ )
+}
+
+// ═══════════════════════════════════════════════════════════════════════════════
+// MAIN ANALYTICS PAGE
+// ═══════════════════════════════════════════════════════════════════════════════
+
+export const AnalyticsPage: React.FC = () => {
+ const { user } = useAuthStore()
+ const navigate = useNavigate()
+
+ const { data, isLoading, error } = useQuery
({
+ queryKey: ['analytics-overview'],
+ queryFn: analyticsAPI.overview,
+ staleTime: 60_000, // 1 min cache
+ retry: false,
+ })
+
+ // Handle plan gate (402 response)
+ if (error && (error as any)?.response?.status === 402) {
+ return (
+
+
+
+
+
+ Analytics Dashboard
+
+ Unlock analytics to see how your chatbots are performing — conversations, user engagement, top questions, and more.
+
+
+ Available on Starter and Pro plans
+
+
+ )
+ }
+
+ if (isLoading) {
+ return (
+
+
+
+ )
+ }
+
+ if (!data) {
+ return (
+
+
+
+ Unable to load analytics. Please try again.
+
+
+ )
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
Analytics
+
+ Track how your chatbots are performing
+
+
+
{data.plan} plan
+
+
+ {/* Usage bar */}
+
+
+
+
+ {/* Overview stat cards */}
+
+ }
+ subtitle={`${data.conversations_this_month} this month`}
+ />
+ }
+ subtitle="Across all chatbots"
+ />
+ }
+ subtitle="Total messages exchanged"
+ />
+ }
+ subtitle={data.average_rating ? 'Across rated chatbots' : 'No ratings yet'}
+ />
+
+
+ {/* Chatbot breakdown header */}
+
+
+ Your chatbots ({data.total_chatbots})
+
+
{data.published_chatbots} published
+
+
+ {/* Per-chatbot expandable rows */}
+ {data.chatbots.length === 0 ? (
+
+
+ No chatbots yet. Create your first chatbot to see analytics.
+
+
+ ) : (
+
+ {data.chatbots.map(cb => (
+
+ ))}
+
+ )}
+
+ )
+}
diff --git a/src/pages/PricingPage.tsx b/src/pages/PricingPage.tsx
index d94a9ba..7a58839 100644
--- a/src/pages/PricingPage.tsx
+++ b/src/pages/PricingPage.tsx
@@ -11,7 +11,7 @@ const PLANS = [
id: 'free',
name: 'Free',
price: 0,
- description: 'Perfect for testing and development',
+ description: 'Build and test chatbots, no credit card needed',
icon: '🆓',
color: 'gray',
features: [
@@ -19,50 +19,54 @@ const PLANS = [
{ text: 'Upload PDF, DOCX, CSV, XLSX', included: true },
{ text: 'Unlimited preview testing', included: true },
{ text: 'Shareable preview links', included: true },
+ { text: '50 preview conversations/month', included: true },
+ { text: '3 documents per chatbot', included: true },
+ { text: 'Llama 3.3 70B model', included: true },
{ text: 'Publish to marketplace', included: false },
- { text: 'Premium AI models', included: false },
- { text: 'Code export', included: false },
{ text: 'Analytics dashboard', included: false },
+ { text: 'Code export', included: false },
],
},
{
id: 'starter',
name: 'Starter',
- price: 39,
- description: 'For small businesses launching their first chatbot',
+ price: 3,
+ description: 'Go live with your first chatbot',
icon: '🚀',
color: 'blue',
- badge: 'Popular',
+ badge: 'Most Popular',
features: [
{ text: 'Everything in Free', included: true },
{ text: 'Publish 1 chatbot to marketplace', included: true },
- { text: 'Fireworks AI models (Llama, Mixtral)', included: true },
- { text: '5,000 conversations/month', included: true },
+ { text: '500 conversations/month', included: true },
+ { text: '10 documents per chatbot', included: true },
+ { text: '4 Fireworks AI models (Qwen3, DeepSeek, Kimi, Llama)', included: true },
{ text: 'Analytics dashboard', included: true },
{ text: 'Custom branding', included: true },
{ text: 'Email support', included: true },
- { text: 'Premium AI models (GPT-4, Claude)', included: false },
+ { text: 'Premium models (GPT-4o, Claude, Gemini)', included: false },
{ text: 'Code export', included: false },
],
},
{
id: 'pro',
name: 'Pro',
- price: 119,
- description: 'For growing businesses with multiple products',
+ price: 20,
+ description: 'For growing businesses with multiple chatbots',
icon: '⚡',
color: 'purple',
highlighted: true,
features: [
{ text: 'Everything in Starter', included: true },
- { text: 'Build & publish 3 chatbots', included: true },
- { text: 'GPT-4o, Claude 3.5, Gemini 1.5', included: true },
- { text: '20,000 conversations/month', included: true },
+ { text: 'Build & publish up to 5 chatbots', included: true },
+ { text: '2,000 conversations/month', included: true },
+ { text: '50 documents per chatbot', included: true },
+ { text: 'GPT-4o, GPT-4o Mini', included: true },
+ { text: 'Claude Haiku 4.5', included: true },
+ { text: 'Gemini 2.5 Flash, Lite & Pro', included: true },
{ text: 'Code export (FastAPI + React widget)', included: true },
{ text: 'Advanced analytics', included: true },
- { text: 'Remove "Powered by" badge', included: true },
{ text: 'Priority support', included: true },
- { text: 'Custom domain', included: true },
],
},
{
@@ -91,11 +95,10 @@ export const PricingPage: React.FC = () => {
const navigate = useNavigate()
const [loading, setLoading] = useState(null)
- // BUG-10 FIX: Fetch current subscription to show "Current Plan" badge
const { data: subscription } = useQuery({
queryKey: ['subscription'],
queryFn: billingAPI.getSubscription,
- enabled: !!user, // Only fetch if logged in
+ enabled: !!user,
})
const currentPlan = subscription?.plan || user?.plan || 'free'
@@ -110,7 +113,6 @@ export const PricingPage: React.FC = () => {
navigate('/dashboard')
return
}
- // BUG-10 FIX: Don't allow re-subscribing to current plan
if (planId === currentPlan) return
setLoading(planId)
@@ -128,7 +130,6 @@ export const PricingPage: React.FC = () => {
}
}
- // Helper to determine CTA text
const getCtaText = (planId: string): string => {
if (!user) return planId === 'enterprise' ? 'Contact Sales' : 'Get Started'
if (planId === currentPlan) return 'Current Plan'
@@ -142,13 +143,12 @@ export const PricingPage: React.FC = () => {
return (
-
Simple, transparent pricing
+
Simple, affordable pricing
- Start free and build as many chatbots as you want. Upgrade when you're ready to publish and go live.
+ Start free, go live for just $3/month. Built for individuals, small businesses, and enterprises alike.
- {/* R-06 FIX: Better grid breakpoints - md:grid-cols-2 instead of jumping to 4 */}
{PLANS.map((plan) => (
{
: 'border-gray-200 bg-white'
}`}
>
- {/* BUG-10 FIX: Show "Current Plan" badge */}
{isCurrentPlan(plan.id) && (
@@ -198,7 +197,8 @@ export const PricingPage: React.FC = () => {
{plan.features.map((feature) => (
@@ -213,7 +213,6 @@ export const PricingPage: React.FC = () => {