From 8fc01e07cb7e8874ab7a56afd1501d8d7be0756f Mon Sep 17 00:00:00 2001 From: pradeepkumar Date: Mon, 20 Apr 2026 23:38:12 +0530 Subject: [PATCH] feat: add subscription status display and approval confirmation modal for unpaid agents --- src/app/dashboard/users/[id]/page.tsx | 84 ++++++++++++++++++++++++++- src/services/users.service.ts | 2 + 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/app/dashboard/users/[id]/page.tsx b/src/app/dashboard/users/[id]/page.tsx index c81b693..337514b 100644 --- a/src/app/dashboard/users/[id]/page.tsx +++ b/src/app/dashboard/users/[id]/page.tsx @@ -39,6 +39,12 @@ export default function UserDetailPage() { const [verificationHistory, setVerificationHistory] = useState([]); const [agentFieldValues, setAgentFieldValues] = useState([]); const [isTogglingStatus, setIsTogglingStatus] = useState(false); + const [pendingApprovalConfirm, setPendingApprovalConfirm] = useState(false); + + // Is the agent subscription active (paid)? + const PAID_STATUSES = new Set(['ACTIVE', 'TRIALING', 'PAST_DUE']); + const isSubscriptionActive = (status?: string | null) => + !!status && PAID_STATUSES.has(status.toUpperCase()); // Helper function to check if avatar is an S3 key const isS3Key = (avatar: string | null | undefined): boolean => { @@ -183,9 +189,23 @@ export default function UserDetailPage() { } }; - const handleVerification = async (status: VerificationStatus) => { + const handleVerification = async ( + status: VerificationStatus, + opts?: { skipPaymentCheck?: boolean }, + ) => { if (!user) return; + // Guard: approving a user without active subscription requires extra confirmation + if ( + status === 'APPROVED' && + !opts?.skipPaymentCheck && + !isSubscriptionActive(user.agentProfile?.subscriptionStatus) + ) { + setPendingApprovalConfirm(true); + return; + } + + setPendingApprovalConfirm(false); setIsUpdatingVerification(true); setError(''); setUpdateSuccess(''); @@ -525,6 +545,29 @@ export default function UserDetailPage() {
+ {/* Payment / subscription status */} +
+
+

Payment Status

+

+ {user.agentProfile.subscriptionStatus || 'No subscription'} +

+
+ {isSubscriptionActive(user.agentProfile.subscriptionStatus) ? ( + + Paid + + ) : ( + + Not Paid + + )} +
+ {/* Verification Info */} {user.agentProfile.isVerified && user.agentProfile.verifiedAt && (
@@ -805,6 +848,45 @@ export default function UserDetailPage() {
)} + + {/* Approve-without-payment confirmation modal */} + {pendingApprovalConfirm && ( +
+
+
+

Approve Without Payment?

+
+
+

+ This user has not paid for a subscription. +

+

+ Approving will mark the profile as verified and it will be visible in + public search results. Payment is not required for visibility. +

+

+ Are you sure you want to approve this profile anyway? +

+
+
+ + +
+
+
+ )} ); } diff --git a/src/services/users.service.ts b/src/services/users.service.ts index a00ea6f..ec03a14 100644 --- a/src/services/users.service.ts +++ b/src/services/users.service.ts @@ -40,6 +40,8 @@ export interface AgentProfileDetails { // Stats averageRating?: number | null; totalReviews?: number | null; + // Subscription / payment status (denormalized from AgentSubscription) + subscriptionStatus?: string | null; } export interface User {