You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
1.6 KiB
TypeScript
61 lines
1.6 KiB
TypeScript
/**
|
|
* Capacity Display Component
|
|
*
|
|
* Shows booking capacity in "booked_count / capacity · remaining" format.
|
|
* Provides visual feedback for slot availability.
|
|
*/
|
|
|
|
import type { BookingSlot } from '@/src/types/bookings';
|
|
|
|
interface CapacityDisplayProps {
|
|
slot: Pick<BookingSlot, 'booked_count' | 'capacity' | 'capacity_remaining'>;
|
|
variant?: 'default' | 'compact' | 'inline';
|
|
className?: string;
|
|
}
|
|
|
|
export default function CapacityDisplay({
|
|
slot,
|
|
variant = 'default',
|
|
className = '',
|
|
}: CapacityDisplayProps) {
|
|
const { booked_count, capacity, capacity_remaining } = slot;
|
|
|
|
// Determine color based on availability
|
|
const availabilityColor =
|
|
capacity_remaining === 0
|
|
? 'text-red-600'
|
|
: capacity_remaining <= 1
|
|
? 'text-orange-600'
|
|
: 'text-slate-700';
|
|
|
|
if (variant === 'compact') {
|
|
return (
|
|
<span className={`text-sm font-medium ${availabilityColor} ${className}`}>
|
|
{booked_count} / {capacity}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
if (variant === 'inline') {
|
|
return (
|
|
<span className={`text-sm ${availabilityColor} ${className}`}>
|
|
{booked_count} / {capacity} booked · {capacity_remaining} remaining
|
|
</span>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={`${className}`}>
|
|
<div className="flex items-baseline space-x-2">
|
|
<span className={`text-lg font-semibold ${availabilityColor}`}>
|
|
{booked_count} / {capacity}
|
|
</span>
|
|
<span className="text-sm text-slate-600">booked</span>
|
|
</div>
|
|
<p className="text-xs text-slate-500 mt-0.5">
|
|
{capacity_remaining} {capacity_remaining === 1 ? 'spot' : 'spots'} remaining
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|