Compare commits
2 Commits
2e2e7f0ae2
...
2101ee3e4f
| Author | SHA1 | Date | |
|---|---|---|---|
| 2101ee3e4f | |||
| df16a76909 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
firebase-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
@@ -7,10 +7,9 @@ const nextConfig: NextConfig = {
|
||||
// Image optimization
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "**",
|
||||
},
|
||||
{ protocol: "https", hostname: "*.contabostorage.com" },
|
||||
{ protocol: "https", hostname: "*.amazonaws.com" },
|
||||
{ protocol: "https", hostname: "*.digitaloceanspaces.com" },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ export default function UserDetailPage() {
|
||||
const [verificationHistory, setVerificationHistory] = useState<VerificationHistoryEntry[]>([]);
|
||||
const [agentFieldValues, setAgentFieldValues] = useState<AgentFieldValue[]>([]);
|
||||
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']);
|
||||
@@ -189,23 +188,9 @@ export default function UserDetailPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleVerification = async (
|
||||
status: VerificationStatus,
|
||||
opts?: { skipPaymentCheck?: boolean },
|
||||
) => {
|
||||
const handleVerification = async (status: VerificationStatus) => {
|
||||
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('');
|
||||
@@ -849,44 +834,6 @@ export default function UserDetailPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Approve-without-payment confirmation modal */}
|
||||
{pendingApprovalConfirm && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
<div className="bg-white rounded-lg shadow-xl max-w-md w-full mx-4">
|
||||
<div className="px-6 py-4 border-b border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-900">Approve Without Payment?</h3>
|
||||
</div>
|
||||
<div className="px-6 py-4 space-y-3">
|
||||
<p className="text-sm text-gray-700">
|
||||
This user has <span className="font-semibold text-red-700">not paid</span> for a subscription.
|
||||
</p>
|
||||
<p className="text-sm text-gray-600">
|
||||
Approving will mark the profile as verified and it will be visible in
|
||||
public search results. Payment is not required for visibility.
|
||||
</p>
|
||||
<p className="text-sm text-gray-600">
|
||||
Are you sure you want to approve this profile anyway?
|
||||
</p>
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 flex justify-end space-x-3">
|
||||
<button
|
||||
onClick={() => setPendingApprovalConfirm(false)}
|
||||
disabled={isUpdatingVerification}
|
||||
className="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors disabled:opacity-50"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleVerification('APPROVED', { skipPaymentCheck: true })}
|
||||
disabled={isUpdatingVerification}
|
||||
className="px-4 py-2 bg-yellow-600 hover:bg-yellow-700 text-white rounded-lg transition-colors disabled:opacity-50"
|
||||
>
|
||||
{isUpdatingVerification ? 'Approving...' : 'Approve Anyway'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user