import React, { useEffect, useState } from 'react';
import api from '../../utils/api';
import { Card } from '../../components/ui/card';
import { Button } from '../../components/ui/button';
import { Badge } from '../../components/ui/badge';
import { Input } from '../../components/ui/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '../../components/ui/select';
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
} from '../../components/ui/table';
import {
Pagination,
PaginationContent,
PaginationLink,
PaginationItem,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
} from '../../components/ui/pagination';
import { toast } from 'sonner';
import { CheckCircle, Clock, Search, ArrowUp, ArrowDown } from 'lucide-react';
import PaymentActivationDialog from '../../components/PaymentActivationDialog';
const AdminApprovals = () => {
const [pendingUsers, setPendingUsers] = useState([]);
const [filteredUsers, setFilteredUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [actionLoading, setActionLoading] = useState(null);
const [paymentDialogOpen, setPaymentDialogOpen] = useState(false);
const [selectedUserForPayment, setSelectedUserForPayment] = useState(null);
// Filtering state
const [searchQuery, setSearchQuery] = useState('');
const [statusFilter, setStatusFilter] = useState('all');
// Pagination state
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(10);
// Sorting state
const [sortBy, setSortBy] = useState('created_at');
const [sortOrder, setSortOrder] = useState('desc');
useEffect(() => {
fetchPendingUsers();
}, []);
useEffect(() => {
filterAndSortUsers();
}, [pendingUsers, searchQuery, statusFilter, sortBy, sortOrder]);
useEffect(() => {
setCurrentPage(1);
}, [searchQuery, statusFilter]);
const fetchPendingUsers = async () => {
try {
const response = await api.get('/admin/users');
const pending = response.data.filter(user =>
['pending_email', 'pending_approval', 'pre_approved', 'payment_pending'].includes(user.status)
);
setPendingUsers(pending);
} catch (error) {
toast.error('Failed to fetch pending users');
} finally {
setLoading(false);
}
};
const filterAndSortUsers = () => {
let filtered = [...pendingUsers];
// Apply status filter
if (statusFilter !== 'all') {
filtered = filtered.filter(user => user.status === statusFilter);
}
// Apply search query
if (searchQuery) {
const query = searchQuery.toLowerCase();
filtered = filtered.filter(user =>
user.first_name.toLowerCase().includes(query) ||
user.last_name.toLowerCase().includes(query) ||
user.email.toLowerCase().includes(query) ||
user.phone?.toLowerCase().includes(query)
);
}
// Apply sorting
filtered.sort((a, b) => {
let aVal = a[sortBy];
let bVal = b[sortBy];
if (sortBy === 'created_at') {
aVal = new Date(aVal);
bVal = new Date(bVal);
} else if (sortBy === 'first_name') {
aVal = `${a.first_name} ${a.last_name}`;
bVal = `${b.first_name} ${b.last_name}`;
}
if (sortOrder === 'asc') {
return aVal > bVal ? 1 : -1;
} else {
return aVal < bVal ? 1 : -1;
}
});
setFilteredUsers(filtered);
};
const handleApprove = async (userId) => {
setActionLoading(userId);
try {
await api.put(`/admin/users/${userId}/approve`);
toast.success('User validated and approved! Payment email sent.');
fetchPendingUsers();
} catch (error) {
toast.error('Failed to approve user');
} finally {
setActionLoading(null);
}
};
const handleBypassAndApprove = async (userId) => {
if (!window.confirm(
'This will bypass email verification and approve the user. ' +
'Are you sure you want to proceed?'
)) {
return;
}
setActionLoading(userId);
try {
await api.put(`/admin/users/${userId}/approve?bypass_email_verification=true`);
toast.success('User email verified and approved! Payment email sent.');
fetchPendingUsers();
} catch (error) {
toast.error(error.response?.data?.detail || 'Failed to approve user');
} finally {
setActionLoading(null);
}
};
const handleActivatePayment = (user) => {
setSelectedUserForPayment(user);
setPaymentDialogOpen(true);
};
const handlePaymentSuccess = () => {
fetchPendingUsers(); // Refresh list
};
const getStatusBadge = (status) => {
const config = {
pending_email: { label: 'Awaiting Email', className: 'bg-orange-100 text-orange-700' },
pending_approval: { label: 'Pending', className: 'bg-gray-200 text-gray-700' },
pre_approved: { label: 'Pre-Approved', className: 'bg-[#81B29A] text-white' },
payment_pending: { label: 'Payment Pending', className: 'bg-orange-500 text-white' }
};
const statusConfig = config[status];
return (
Review and approve pending membership applications.
Total Pending
{pendingUsers.length}
Awaiting Email
{pendingUsers.filter(u => u.status === 'pending_email').length}
Pending Approval
{pendingUsers.filter(u => u.status === 'pending_approval').length}
Pre-Approved
{pendingUsers.filter(u => u.status === 'pre_approved').length}
Payment Pending
{pendingUsers.filter(u => u.status === 'payment_pending').length}
Loading pending applications...
Show
entries (showing {(currentPage - 1) * itemsPerPage + 1}- {Math.min(currentPage * itemsPerPage, filteredUsers.length)} of {filteredUsers.length})
{searchQuery || statusFilter !== 'all' ? 'Try adjusting your filters' : 'All applications have been reviewed!'}