From 2ed7ba8808334d593dde684f4ac3235aeedfb2cd Mon Sep 17 00:00:00 2001
From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com>
Date: Mon, 10 Nov 2025 20:47:00 +0000
Subject: fix: past due pending users improvements (#572)
---
apps/web/components/views/billing.tsx | 62 +++++++++++++++++++++++--------
apps/web/components/views/profile.tsx | 69 ++++++++++++++++++++++++++---------
packages/lib/queries.ts | 28 ++++++++++----
3 files changed, 120 insertions(+), 39 deletions(-)
diff --git a/apps/web/components/views/billing.tsx b/apps/web/components/views/billing.tsx
index d6d85884..f3ef2605 100644
--- a/apps/web/components/views/billing.tsx
+++ b/apps/web/components/views/billing.tsx
@@ -7,7 +7,7 @@ import {
import { Button } from "@ui/components/button"
import { HeadingH3Bold } from "@ui/text/heading/heading-h3-bold"
import { useCustomer } from "autumn-js/react"
-import { CheckCircle, LoaderIcon, X } from "lucide-react"
+import { AlertTriangle, CheckCircle, LoaderIcon, X } from "lucide-react"
import { motion } from "motion/react"
import Link from "next/link"
import { useEffect, useState } from "react"
@@ -24,11 +24,16 @@ export function BillingView() {
const {
data: status = {
- consumer_pro: null,
+ consumer_pro: { allowed: false, status: null },
},
isLoading: isCheckingStatus,
} = fetchSubscriptionStatus(autumn, !autumn.isLoading)
+ const proStatus = status.consumer_pro
+ const proProductStatus = proStatus?.status
+ const isPastDue = proProductStatus === "past_due"
+ const hasProProduct = proProductStatus !== null
+
const { data: memoriesCheck } = fetchMemoriesFeature(
autumn,
!autumn.isLoading && !isCheckingStatus,
@@ -37,7 +42,10 @@ export function BillingView() {
const memoriesUsed = memoriesCheck?.usage ?? 0
const memoriesLimit = memoriesCheck?.included_usage ?? 0
- const { data: connectionsCheck } = fetchConnectionsFeature(autumn, !autumn.isLoading && !isCheckingStatus)
+ const { data: connectionsCheck } = fetchConnectionsFeature(
+ autumn,
+ !autumn.isLoading && !isCheckingStatus,
+ )
const connectionsUsed = connectionsCheck?.usage ?? 0
@@ -66,8 +74,6 @@ export function BillingView() {
})
}
- const isPro = status.consumer_pro
-
if (user?.isAnonymous) {
return (
Pro Plan
-
- Active
-
+ {isPastDue ? (
+
+ Past Due
+
+ ) : (
+
+ Active
+
+ )}
- You're enjoying expanded memory capacity with supermemory Pro!
+ {isPastDue
+ ? "Your payment is past due. Please update your payment method to restore access."
+ : "You're enjoying expanded memory capacity with supermemory Pro!"}
+ {isPastDue && (
+
+
+
+
+ Payment Required
+
+
+ Your payment method failed or payment is past due. Update your
+ payment information to restore access to all Pro features.
+
+
+
+ )}
+
{/* Current Usage */}
Current Usage
Memories
-
- Unlimited
-
+ Unlimited
@@ -132,8 +159,13 @@ export function BillingView() {
-
)
diff --git a/apps/web/components/views/profile.tsx b/apps/web/components/views/profile.tsx
index e4db2171..c60f4310 100644
--- a/apps/web/components/views/profile.tsx
+++ b/apps/web/components/views/profile.tsx
@@ -10,7 +10,14 @@ import { Button } from "@repo/ui/components/button"
import { Skeleton } from "@repo/ui/components/skeleton"
import { HeadingH3Bold } from "@repo/ui/text/heading/heading-h3-bold"
import { useCustomer } from "autumn-js/react"
-import { CheckCircle, CreditCard, LoaderIcon, User, X } from "lucide-react"
+import {
+ AlertTriangle,
+ CheckCircle,
+ CreditCard,
+ LoaderIcon,
+ User,
+ X,
+} from "lucide-react"
import { motion } from "motion/react"
import Link from "next/link"
import { useState } from "react"
@@ -23,12 +30,16 @@ export function ProfileView() {
const {
data: status = {
- consumer_pro: null,
+ consumer_pro: { allowed: false, status: null },
},
isLoading: isCheckingStatus,
} = fetchSubscriptionStatus(autumn, !autumn.isLoading)
- const isPro = status.consumer_pro
+ const proStatus = status.consumer_pro
+ const isPro = proStatus?.allowed ?? false
+ const proProductStatus = proStatus?.status
+ const isPastDue = proProductStatus === "past_due"
+ const hasProProduct = proProductStatus !== null
const { data: memoriesCheck } = fetchMemoriesFeature(
autumn,
@@ -176,24 +187,43 @@ export function ProfileView() {
- {isPro ? "Pro Plan" : "Free Plan"}
- {isPro && (
+ {hasProProduct ? "Pro Plan" : "Free Plan"}
+ {isPastDue ? (
+
+ Past Due
+
+ ) : isPro ? (
Active
- )}
+ ) : null}
- {isPro ? "Expanded memory capacity" : "Basic plan"}
+ {hasProProduct ? "Expanded memory capacity" : "Basic plan"}
+ {isPastDue && (
+
+
+
+
+ Payment Required
+
+
+ Your payment is past due. Please update your payment method to
+ restore access to Pro features.
+
+
+
+ )}
+
{/* Usage Stats */}
Memories
- {isPro ? (
+ {hasProProduct ? (
Unlimited
) : (
)}
- {!isPro && (
+ {!hasProProduct && (
= memoriesLimit
- ? "bg-red-500"
- : isPro
- ? "bg-green-500"
- : "bg-blue-500"
+ memoriesUsed >= memoriesLimit ? "bg-red-500" : "bg-blue-500"
}`}
style={{
width: `${Math.min((memoriesUsed / memoriesLimit) * 100, 100)}%`,
@@ -221,7 +247,7 @@ export function ProfileView() {
)}
- {isPro && (
+ {hasProProduct && (
Connections
@@ -232,7 +258,16 @@ export function ProfileView() {
{/* Billing Actions */}
- {isPro ? (
+ {isPastDue ? (
+
+ Pay Past Due
+
+ ) : hasProProduct ? (
- {!isPro && (
+ {!hasProProduct && (
{/* Free Plan */}
diff --git a/packages/lib/queries.ts b/packages/lib/queries.ts
index 23084d33..254b3bc9 100644
--- a/packages/lib/queries.ts
+++ b/packages/lib/queries.ts
@@ -14,10 +14,11 @@ export const fetchSubscriptionStatus = (
) =>
useQuery({
queryFn: async () => {
- const allPlans = [
- "consumer_pro",
- ]
- const statusMap: Record = {}
+ const allPlans = ["consumer_pro"]
+ const statusMap: Record<
+ string,
+ { allowed: boolean; status: string | null }
+ > = {}
await Promise.all(
allPlans.map(async (plan) => {
@@ -25,10 +26,20 @@ export const fetchSubscriptionStatus = (
const res = autumn.check({
productId: plan,
})
- statusMap[plan] = res.data?.allowed ?? false
+ const allowed = res.data?.allowed ?? false
+
+ const product = autumn.customer?.products?.find(
+ (p) => p.id === plan,
+ )
+ const productStatus = product?.status ?? null
+
+ statusMap[plan] = {
+ allowed,
+ status: productStatus,
+ }
} catch (error) {
console.error(`Error checking status for ${plan}:`, error)
- statusMap[plan] = false
+ statusMap[plan] = { allowed: false, status: null }
}
}),
)
@@ -42,7 +53,10 @@ export const fetchSubscriptionStatus = (
})
// Feature checks
-export const fetchMemoriesFeature = (autumn: ReturnType, isEnabled: boolean) =>
+export const fetchMemoriesFeature = (
+ autumn: ReturnType,
+ isEnabled: boolean,
+) =>
useQuery({
queryFn: async () => {
const res = autumn.check({ featureId: "memories" })
--
cgit v1.2.3