Donation status badge upates, admin validation tootips
This commit is contained in:
@@ -6,7 +6,6 @@ const STATUS_BADGE_CONFIG = {
|
|||||||
//status-based badges
|
//status-based badges
|
||||||
pending_email: { label: 'Pending Email', variant: 'orange2' },
|
pending_email: { label: 'Pending Email', variant: 'orange2' },
|
||||||
pending_validation: { label: 'Pending Validation', variant: 'gray' },
|
pending_validation: { label: 'Pending Validation', variant: 'gray' },
|
||||||
pre_validated: { label: 'Pre-Validated', variant: 'green' },
|
|
||||||
payment_pending: { label: 'Payment Pending', variant: 'orange' },
|
payment_pending: { label: 'Payment Pending', variant: 'orange' },
|
||||||
active: { label: 'Active', variant: 'green' },
|
active: { label: 'Active', variant: 'green' },
|
||||||
inactive: { label: 'Inactive', variant: 'gray2' },
|
inactive: { label: 'Inactive', variant: 'gray2' },
|
||||||
@@ -23,7 +22,12 @@ const STATUS_BADGE_CONFIG = {
|
|||||||
admin: { label: 'Admin', variant: 'purple' },
|
admin: { label: 'Admin', variant: 'purple' },
|
||||||
moderator: { label: 'Moderator', variant: 'bg-[var(--neutral-800)] text-[var(--purple-ink)]' },
|
moderator: { label: 'Moderator', variant: 'bg-[var(--neutral-800)] text-[var(--purple-ink)]' },
|
||||||
staff: { label: 'Staff', variant: 'gray' },
|
staff: { label: 'Staff', variant: 'gray' },
|
||||||
media: { label: 'Media', variant: 'gray2' }
|
media: { label: 'Media', variant: 'gray2' },
|
||||||
|
|
||||||
|
//donation badges
|
||||||
|
pending: { label: 'Payment Pending', variant: 'orange' },
|
||||||
|
completed: { label: 'Completed', variant: 'green' },
|
||||||
|
failed: { label: 'Failed', className: 'bg-red-100 text-red-700' }
|
||||||
};
|
};
|
||||||
|
|
||||||
//todo: make shield icon dynamic based on status
|
//todo: make shield icon dynamic based on status
|
||||||
|
|||||||
@@ -1,78 +1,91 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const Table = React.forwardRef(({ className, ...props }, ref) => (
|
const Table = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<div className="relative w-full overflow-auto">
|
<div className="relative w-full overflow-auto">
|
||||||
<table
|
<table ref={ref} className={cn("w-full", className)} {...props} />
|
||||||
ref={ref}
|
|
||||||
className={cn("w-full caption-bottom text-sm", className)}
|
|
||||||
{...props} />
|
|
||||||
</div>
|
</div>
|
||||||
))
|
));
|
||||||
Table.displayName = "Table"
|
Table.displayName = "Table";
|
||||||
|
|
||||||
const TableHeader = React.forwardRef(({ className, ...props }, ref) => (
|
const TableHeader = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
<thead
|
||||||
))
|
ref={ref}
|
||||||
TableHeader.displayName = "TableHeader"
|
className={cn(
|
||||||
|
"bg-[var(--lavender-300)] border-b border-[var(--neutral-800)]",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableHeader.displayName = "TableHeader";
|
||||||
|
|
||||||
const TableBody = React.forwardRef(({ className, ...props }, ref) => (
|
const TableBody = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<tbody
|
<tbody
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("[&_tr:last-child]:border-0", className)}
|
className={cn("[&_tr:last-child]:border-0", className)}
|
||||||
{...props} />
|
{...props}
|
||||||
))
|
/>
|
||||||
TableBody.displayName = "TableBody"
|
));
|
||||||
|
TableBody.displayName = "TableBody";
|
||||||
|
|
||||||
const TableFooter = React.forwardRef(({ className, ...props }, ref) => (
|
const TableFooter = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<tfoot
|
<tfoot
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
|
className={cn(
|
||||||
{...props} />
|
"border-t border-[var(--neutral-800)] font-medium [&>tr]:last:border-b-0",
|
||||||
))
|
className,
|
||||||
TableFooter.displayName = "TableFooter"
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
TableFooter.displayName = "TableFooter";
|
||||||
|
|
||||||
const TableRow = React.forwardRef(({ className, ...props }, ref) => (
|
const TableRow = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<tr
|
<tr
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
"border-b border-[var(--neutral-800)] transition-colors hover:bg-[var(--lavender-400)]",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props} />
|
{...props}
|
||||||
))
|
/>
|
||||||
TableRow.displayName = "TableRow"
|
));
|
||||||
|
TableRow.displayName = "TableRow";
|
||||||
|
|
||||||
const TableHead = React.forwardRef(({ className, ...props }, ref) => (
|
const TableHead = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<th
|
<th
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
"p-4 text-left align-middle font-semibold text-[var(--purple-ink)] [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props} />
|
{...props}
|
||||||
))
|
/>
|
||||||
TableHead.displayName = "TableHead"
|
));
|
||||||
|
TableHead.displayName = "TableHead";
|
||||||
|
|
||||||
const TableCell = React.forwardRef(({ className, ...props }, ref) => (
|
const TableCell = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<td
|
<td
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
"p-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] ",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
{...props} />
|
{...props}
|
||||||
))
|
/>
|
||||||
TableCell.displayName = "TableCell"
|
));
|
||||||
|
TableCell.displayName = "TableCell";
|
||||||
|
|
||||||
const TableCaption = React.forwardRef(({ className, ...props }, ref) => (
|
const TableCaption = React.forwardRef(({ className, ...props }, ref) => (
|
||||||
<caption
|
<caption
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||||
{...props} />
|
{...props}
|
||||||
))
|
/>
|
||||||
TableCaption.displayName = "TableCaption"
|
));
|
||||||
|
TableCaption.displayName = "TableCaption";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Table,
|
Table,
|
||||||
@@ -83,4 +96,4 @@ export {
|
|||||||
TableRow,
|
TableRow,
|
||||||
TableCell,
|
TableCell,
|
||||||
TableCaption,
|
TableCaption,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useAuth } from '../../context/AuthContext';
|
|||||||
import { Card } from '../../components/ui/card';
|
import { Card } from '../../components/ui/card';
|
||||||
import { Button } from '../../components/ui/button';
|
import { Button } from '../../components/ui/button';
|
||||||
import { Input } from '../../components/ui/input';
|
import { Input } from '../../components/ui/input';
|
||||||
|
import StatusBadge from '@/components/StatusBadge';
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@@ -17,6 +18,14 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '../../components/ui/dropdown-menu';
|
} from '../../components/ui/dropdown-menu';
|
||||||
import { Badge } from '../../components/ui/badge';
|
import { Badge } from '../../components/ui/badge';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from '../../components/ui/table';
|
||||||
import api from '../../utils/api';
|
import api from '../../utils/api';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import {
|
import {
|
||||||
@@ -184,15 +193,8 @@ const AdminDonations = () => {
|
|||||||
toast.error('Failed to copy to clipboard');
|
toast.error('Failed to copy to clipboard');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
const getStatusBadgeVariant = (status) => {
|
*/
|
||||||
const variants = {
|
|
||||||
completed: 'default',
|
|
||||||
pending: 'secondary',
|
|
||||||
failed: 'destructive'
|
|
||||||
};
|
|
||||||
return variants[status] || 'outline';
|
|
||||||
};
|
|
||||||
|
|
||||||
const getTypeBadgeColor = (type) => {
|
const getTypeBadgeColor = (type) => {
|
||||||
return type === 'member' ? 'bg-[var(--green-light)]' : 'bg-brand-purple ';
|
return type === 'member' ? 'bg-[var(--green-light)]' : 'bg-brand-purple ';
|
||||||
@@ -392,51 +394,37 @@ const AdminDonations = () => {
|
|||||||
{/* Donations Table */}
|
{/* Donations Table */}
|
||||||
<Card className="bg-background rounded-2xl border-2 border-[var(--neutral-800)] overflow-hidden">
|
<Card className="bg-background rounded-2xl border-2 border-[var(--neutral-800)] overflow-hidden">
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full">
|
<Table>
|
||||||
<thead className="bg-[var(--lavender-300)] border-b-2 border-[var(--neutral-800)]">
|
<TableHeader>
|
||||||
<tr>
|
<TableRow>
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<TableHead>Donor</TableHead>
|
||||||
Donor
|
<TableHead>Type</TableHead>
|
||||||
</th>
|
<TableHead>Amount</TableHead>
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<TableHead>Status</TableHead>
|
||||||
Type
|
<TableHead>Date</TableHead>
|
||||||
</th>
|
<TableHead>Payment Method</TableHead>
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<TableHead className="text-center">Details</TableHead>
|
||||||
Amount
|
</TableRow>
|
||||||
</th>
|
</TableHeader>
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<TableBody>
|
||||||
Status
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
|
||||||
Date
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
|
||||||
Payment Method
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-center text-sm font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
|
||||||
Details
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-[var(--neutral-800)]">
|
|
||||||
{filteredDonations.length === 0 ? (
|
{filteredDonations.length === 0 ? (
|
||||||
<tr>
|
<TableRow>
|
||||||
<td colSpan="7" className="px-6 py-12 text-center">
|
<TableCell colSpan={7} className="p-12 text-center">
|
||||||
<div className="flex flex-col items-center gap-3">
|
<div className="flex flex-col items-center gap-3">
|
||||||
<Heart className="h-12 w-12 text-[var(--neutral-800)]" />
|
<Heart className="h-12 w-12 text-[var(--neutral-800)]" />
|
||||||
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{donations.length === 0 ? 'No donations yet' : 'No donations match your filters'}
|
{donations.length === 0 ? 'No donations yet' : 'No donations match your filters'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</TableCell>
|
||||||
</tr>
|
</TableRow>
|
||||||
) : (
|
) : (
|
||||||
filteredDonations.map((donation) => {
|
filteredDonations.map((donation) => {
|
||||||
const isExpanded = expandedRows.has(donation.id);
|
const isExpanded = expandedRows.has(donation.id);
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={donation.id}>
|
<React.Fragment key={donation.id}>
|
||||||
<tr className="hover:bg-[var(--lavender-400)] transition-colors">
|
<TableRow>
|
||||||
<td className="px-6 py-4">
|
<TableCell>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<p className="font-medium text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
{donation.donor_name || 'Anonymous'}
|
{donation.donor_name || 'Anonymous'}
|
||||||
@@ -445,39 +433,37 @@ const AdminDonations = () => {
|
|||||||
{donation.donor_email || 'No email'}
|
{donation.donor_email || 'No email'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="px-6 py-4">
|
<TableCell>
|
||||||
<Badge
|
<Badge
|
||||||
className={`${getTypeBadgeColor(donation.donation_type)} text-white border-none rounded-full px-3 py-1`}
|
className={`${getTypeBadgeColor(donation.donation_type)} text-white border-none px-3 py-1`}
|
||||||
style={{ fontFamily: "'Inter', sans-serif" }}
|
style={{ fontFamily: "'Inter', sans-serif" }}
|
||||||
>
|
>
|
||||||
{donation.donation_type === 'member' ? 'Member' : 'Public'}
|
{donation.donation_type === 'member' ? 'Member' : 'Public'}
|
||||||
</Badge>
|
</Badge>
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="px-6 py-4">
|
<TableCell>
|
||||||
<p className="font-semibold text-[var(--purple-ink)] text-lg" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<p className="font-semibold text-[var(--purple-ink)] text-lg" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
{donation.amount}
|
{donation.amount}
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="px-6 py-4">
|
<TableCell>
|
||||||
<Badge variant={getStatusBadgeVariant(donation.status)} className="rounded-full">
|
<StatusBadge status={donation.status} />
|
||||||
{donation.status.charAt(0).toUpperCase() + donation.status.slice(1)}
|
</TableCell>
|
||||||
</Badge>
|
<TableCell>
|
||||||
</td>
|
|
||||||
<td className="px-6 py-4">
|
|
||||||
<div className="flex items-center gap-2 text-brand-purple ">
|
<div className="flex items-center gap-2 text-brand-purple ">
|
||||||
<Calendar className="h-4 w-4" />
|
<Calendar className="h-4 w-4" />
|
||||||
<span style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
<span style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||||
{formatDate(donation.created_at)}
|
{formatDate(donation.created_at)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="px-6 py-4">
|
<TableCell>
|
||||||
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
<p className="text-brand-purple " style={{ fontFamily: "'Nunito Sans', sans-serif capitalize" }}>
|
||||||
{donation.payment_method || 'N/A'}
|
{donation.payment_method || 'N/A'}
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</TableCell>
|
||||||
<td className="px-6 py-4 text-center">
|
<TableCell className="text-center">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -486,12 +472,11 @@ const AdminDonations = () => {
|
|||||||
>
|
>
|
||||||
{isExpanded ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
{isExpanded ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
</td>
|
</TableCell>
|
||||||
</tr>
|
</TableRow>
|
||||||
{/* Expandable Details Row */}
|
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<tr className="bg-[var(--lavender-400)]/30">
|
<TableRow className="bg-[var(--lavender-400)]/30">
|
||||||
<td colSpan="7" className="px-6 py-6">
|
<TableCell colSpan={7} className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h4 className="font-semibold text-[var(--purple-ink)] text-lg mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
<h4 className="font-semibold text-[var(--purple-ink)] text-lg mb-4" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||||
Transaction Details
|
Transaction Details
|
||||||
@@ -601,15 +586,15 @@ const AdminDonations = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</TableCell>
|
||||||
</tr>
|
</TableRow>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</TableBody>
|
||||||
</table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
TableCell,
|
TableCell,
|
||||||
} from '../../components/ui/table';
|
} from '../../components/ui/table';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '../../components/ui/tooltip';
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
PaginationContent,
|
PaginationContent,
|
||||||
@@ -417,7 +423,7 @@ const AdminValidations = () => {
|
|||||||
<Card className="bg-background rounded-2xl border border-[var(--neutral-800)] overflow-hidden">
|
<Card className="bg-background rounded-2xl border border-[var(--neutral-800)] overflow-hidden">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow className="text-md">
|
||||||
<TableHead
|
<TableHead
|
||||||
className="cursor-pointer hover:bg-[var(--neutral-800)]/20"
|
className="cursor-pointer hover:bg-[var(--neutral-800)]/20"
|
||||||
onClick={() => handleSort('first_name')}
|
onClick={() => handleSort('first_name')}
|
||||||
@@ -482,8 +488,8 @@ const AdminValidations = () => {
|
|||||||
onValueChange={(action) => handleActionSelect(user, action)}
|
onValueChange={(action) => handleActionSelect(user, action)}
|
||||||
disabled={actionLoading === user.id || resendLoading === user.id}
|
disabled={actionLoading === user.id || resendLoading === user.id}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px] h-9 border-[var(--neutral-800)]">
|
<SelectTrigger className="w-[100px] h-9 border-[var(--neutral-800)]">
|
||||||
<SelectValue placeholder={actionLoading === user.id || resendLoading === user.id ? 'Processing...' : 'Select Action'} />
|
<SelectValue placeholder={actionLoading === user.id || resendLoading === user.id ? 'Processing...' : 'Action'} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{user.status === 'rejected' ? (
|
{user.status === 'rejected' ? (
|
||||||
@@ -521,29 +527,45 @@ const AdminValidations = () => {
|
|||||||
)}
|
)}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
{/* view registration */}
|
<TooltipProvider>
|
||||||
<Button
|
{/* view registration */}
|
||||||
onClick={() => handleRegistrationDialog(user)}
|
<Tooltip>
|
||||||
disabled={actionLoading === user.id}
|
<TooltipTrigger asChild>
|
||||||
size="sm"
|
<Button
|
||||||
variant="outline"
|
onClick={() => handleRegistrationDialog(user)}
|
||||||
className="border-2 border-primary text-primary hover:bg-red-50 dark:hover:bg-red-500/10"
|
disabled={actionLoading === user.id}
|
||||||
>
|
size="sm"
|
||||||
<FileText className="size-4" />
|
variant="outline"
|
||||||
</Button>
|
className="border-2 border-primary text-primary hover:bg-red-50 dark:hover:bg-red-500/10"
|
||||||
|
>
|
||||||
|
<FileText className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
View registration
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{/* reject */}
|
{/* reject */}
|
||||||
{hasPermission('users.approve') && (
|
{hasPermission('users.approve') && (
|
||||||
<Button
|
<Tooltip>
|
||||||
onClick={() => handleRejectUser(user)}
|
<TooltipTrigger asChild>
|
||||||
disabled={actionLoading === user.id}
|
<Button
|
||||||
size="sm"
|
onClick={() => handleRejectUser(user)}
|
||||||
variant="outline"
|
disabled={actionLoading === user.id}
|
||||||
className="border-2 mr-2 border-red-500 text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10"
|
size="sm"
|
||||||
>
|
variant="outline"
|
||||||
X
|
className="border-2 mr-2 border-red-500 text-red-500 hover:bg-red-50 dark:hover:bg-red-500/10"
|
||||||
</Button>
|
>
|
||||||
)}
|
X
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
Reject user
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|||||||
Reference in New Issue
Block a user