pmtool / src /components /asset-request /AssetAvailabilityIndicator.tsx
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
4.07 kB
import React from 'react';
import { Badge } from '@/components/ui/badge';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { CheckCircle, AlertTriangle, XCircle } from 'lucide-react';
import { cn } from '@/lib/utils';
interface AssetAvailabilityIndicatorProps {
assetType: string;
requested: number;
available: number;
className?: string;
showTooltip?: boolean;
}
/**
* Availability indicator component showing asset availability status
* Displays available vs requested quantity with color coding
*/
const AssetAvailabilityIndicator: React.FC<AssetAvailabilityIndicatorProps> = ({
assetType,
requested,
available,
className,
showTooltip = true,
}) => {
// Determine availability status
const getAvailabilityStatus = () => {
if (available >= requested) {
return 'available'; // Green: fully available
} else if (available > 0) {
return 'partial'; // Yellow: partially available
} else {
return 'unavailable'; // Red: not available
}
};
const status = getAvailabilityStatus();
const canFulfill = available >= requested;
// Get icon for availability status
const getStatusIcon = () => {
switch (status) {
case 'available':
return <CheckCircle className="h-3.5 w-3.5" aria-hidden="true" />;
case 'partial':
return <AlertTriangle className="h-3.5 w-3.5" aria-hidden="true" />;
case 'unavailable':
return <XCircle className="h-3.5 w-3.5" aria-hidden="true" />;
}
};
// Get color classes for status
const getStatusColor = () => {
switch (status) {
case 'available':
return 'bg-green-100 text-green-800 border-green-200 hover:bg-green-200';
case 'partial':
return 'bg-yellow-100 text-yellow-800 border-yellow-200 hover:bg-yellow-200';
case 'unavailable':
return 'bg-red-100 text-red-800 border-red-200 hover:bg-red-200';
}
};
// Get tooltip description
const getTooltipContent = () => {
const shortfall = requested - available;
switch (status) {
case 'available':
return (
<div className="space-y-1">
<p className="font-semibold">Fully Available</p>
<p>Requested: {requested} {assetType}</p>
<p>Available: {available} {assetType}</p>
<p className="text-green-400">✓ Can fulfill this request</p>
</div>
);
case 'partial':
return (
<div className="space-y-1">
<p className="font-semibold">Partially Available</p>
<p>Requested: {requested} {assetType}</p>
<p>Available: {available} {assetType}</p>
<p className="text-yellow-400">⚠ Short by {shortfall} unit{shortfall !== 1 ? 's' : ''}</p>
</div>
);
case 'unavailable':
return (
<div className="space-y-1">
<p className="font-semibold">Not Available</p>
<p>Requested: {requested} {assetType}</p>
<p>Available: {available} {assetType}</p>
<p className="text-red-400">✗ Cannot fulfill this request</p>
</div>
);
}
};
const badgeContent = (
<Badge
variant="outline"
className={cn(
'flex items-center gap-1.5 font-medium',
getStatusColor(),
className
)}
aria-label={`${assetType} availability: ${available} of ${requested} available`}
>
{getStatusIcon()}
<span>
{available}/{requested}
</span>
</Badge>
);
if (!showTooltip) {
return badgeContent;
}
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
{badgeContent}
</TooltipTrigger>
<TooltipContent>
{getTooltipContent()}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};
export default AssetAvailabilityIndicator;