feat: added theme success and warning colors

fix: invite member dialog box
feat: email expiry date column
feat: resend email verification button
fix: select item text can be seen
This commit is contained in:
2026-01-28 15:03:46 -06:00
parent 01722edad9
commit a247ac5219
6 changed files with 382 additions and 52 deletions

View File

@@ -61,6 +61,9 @@ const AdminValidations = () => {
const [sortBy, setSortBy] = useState('created_at');
const [sortOrder, setSortOrder] = useState('desc');
// Resend email state
const [resendLoading, setResendLoading] = useState(null);
useEffect(() => {
fetchPendingUsers();
}, []);
@@ -238,6 +241,21 @@ const AdminValidations = () => {
// Resend Email Handler
const handleResendVerification = async (user) => {
setResendLoading(user.id);
try {
await api.post(`/admin/users/${user.id}/resend-verification`);
toast.success(`Verification email sent to ${user.email}`);
fetchPendingUsers();
} catch (error) {
toast.error(error.response?.data?.detail || 'Failed to send verification email');
} finally {
setResendLoading(null);
}
};
const handleSort = (column) => {
if (sortBy === column) {
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');
@@ -279,7 +297,7 @@ const AdminValidations = () => {
<div className=' text-2xl text-[var(--purple-ink)] pb-8 font-semibold'>
Quick Overview
</div>
<div className="grid grid-cols-2 md:grid-cols-6 gap-4">
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
<StatCard
title="Total Pending"
value={loading ? '-' : pendingUsers.length}
@@ -304,14 +322,6 @@ const AdminValidations = () => {
dataTestId="stat-pending-validation"
/>
<StatCard
title="Pre-Validated"
value={loading ? '-' : pendingUsers.filter(u => u.status === 'pre_validated').length}
icon={CheckCircle}
iconBgClass="text-brand-purple"
dataTestId="stat-pre-validated"
/>
<StatCard
title="Payment Pending"
value={loading ? '-' : pendingUsers.filter(u => u.status === 'payment_pending').length}
@@ -349,13 +359,12 @@ const AdminValidations = () => {
<SelectTrigger className="h-14 rounded-xl border-2 border-[var(--neutral-800)]">
<SelectValue placeholder="Filter by status" />
</SelectTrigger>
<SelectContent>
<SelectContent className="">
<SelectItem value="all">All Statuses</SelectItem>
<SelectItem value="pending_email">Awaiting Email</SelectItem>
<SelectItem value="pending_validation">Pending Validation</SelectItem>
<SelectItem value="pre_validated">Pre-Validated</SelectItem>
<SelectItem value="payment_pending">Payment Pending</SelectItem>
<SelectItem value="rejected">Rejected</SelectItem>
<SelectItem value="pending_email" >Awaiting Email</SelectItem>
<SelectItem value="pending_validation" >Pending Validation</SelectItem>
<SelectItem value="payment_pending" >Payment Pending</SelectItem>
<SelectItem value="rejected" >Rejected</SelectItem>
</SelectContent>
</Select>
</div>
@@ -392,6 +401,13 @@ const AdminValidations = () => {
>
Registered {renderSortIcon('created_at')}
</TableHead>
<TableHead
className="cursor-pointer hover:bg-[var(--neutral-800)]/20"
onClick={() => handleSort('email_verification_expires_at')}
>
{/* TODO: change ' ' */}
Validation Expiry {renderSortIcon('email_verification_expires_at')}
</TableHead>
<TableHead>Referred By</TableHead>
<TableHead>Actions</TableHead>
</TableRow>
@@ -408,6 +424,11 @@ const AdminValidations = () => {
<TableCell>
{new Date(user.created_at).toLocaleDateString()}
</TableCell>
<TableCell>
{user.email_verification_expires_at
? new Date(user.email_verification_expires_at).toLocaleString()
: '—'}
</TableCell>
<TableCell>
{user.referred_by_member_name || '-'}
</TableCell>
@@ -429,11 +450,21 @@ const AdminValidations = () => {
onClick={() => handleBypassAndValidateRequest(user)}
disabled={actionLoading === user.id}
size="sm"
className="bg-[var(--neutral-800)] text-[var(--purple-ink)] hover:bg-background"
className="bg-secondary text-[var(--purple-ink)] hover:bg-secondary/80"
>
{actionLoading === user.id ? 'Validating...' : 'Bypass & Validate'}
</Button>
)}
{hasPermission('users.approve') && (
<Button
disabled={resendLoading === user.id}
onClick={() => handleResendVerification(user)}
size="sm"
className=" bg-secondary text-[var(--purple-ink)] hover:bg-secondary/80"
>
{resendLoading === user.id ? 'Sending...' : 'Resend email'}
</Button>
)}
{hasPermission('users.approve') && (
<Button
onClick={() => handleRejectUser(user)}
@@ -442,7 +473,6 @@ const AdminValidations = () => {
variant="outline"
className="border-2 border-red-500 text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10"
>
<X className="h-4 w-4 mr-1" />
Reject
</Button>
)}
@@ -455,7 +485,6 @@ const AdminValidations = () => {
size="sm"
className="btn-light-lavender"
>
<CheckCircle className="h-4 w-4 mr-1" />
Activate Payment
</Button>
)}
@@ -467,7 +496,6 @@ const AdminValidations = () => {
variant="outline"
className="border-2 border-red-500 text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10"
>
<X className="h-4 w-4 mr-1" />
Reject
</Button>
)}
@@ -492,7 +520,6 @@ const AdminValidations = () => {
variant="outline"
className="border-2 border-red-500 text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10"
>
<X className="h-4 w-4 mr-1" />
Reject
</Button>
)}