Spaces:
Sleeping
Sleeping
| 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; | |