Files
blackcanyontickets/reactrebuild0825/src/components/skeleton/TableSkeleton.tsx
dzinesco aa81eb5adb feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-26 09:25:10 -06:00

108 lines
3.6 KiB
TypeScript

import React from 'react';
import { clsx } from 'clsx';
import { Card } from '@/components/ui/Card';
import { Skeleton } from '@/components/loading/Skeleton';
interface TableSkeletonProps {
rows?: number;
columns?: number;
hasHeader?: boolean;
hasActions?: boolean;
hasAvatar?: boolean;
className?: string;
}
/**
* Loading skeleton for data tables
* Provides flexible column and row configuration with realistic table structure
*/
export const TableSkeleton: React.FC<TableSkeletonProps> = ({
rows = 8,
columns = 5,
hasHeader = true,
hasActions = true,
hasAvatar = false,
className = ''
}) => {
// Adjust effective columns based on avatar and actions
const effectiveColumns = hasActions ? columns : columns;
return (
<Card className={clsx('overflow-hidden', className)}>
{/* Table header */}
{hasHeader && (
<div className="bg-glass-bg border-b border-glass-border px-6 py-4">
<div className={clsx(
'grid gap-4 items-center',
`grid-cols-${Math.min(effectiveColumns, 6)}`
)}>
{Array.from({ length: effectiveColumns }).map((_, index) => (
<Skeleton.Base key={`header-${index}`} className="h-4 w-3/4" />
))}
</div>
</div>
)}
{/* Table rows */}
<div className="divide-y divide-glass-border">
{Array.from({ length: rows }).map((_, rowIndex) => (
<div key={`row-${rowIndex}`} className="px-6 py-4">
<div className={clsx(
'grid gap-4 items-center',
`grid-cols-${Math.min(effectiveColumns, 6)}`
)}>
{Array.from({ length: effectiveColumns }).map((_, colIndex) => {
// First column with optional avatar
if (colIndex === 0) {
return (
<div key={`col-${colIndex}`} className="flex items-center space-x-3">
{hasAvatar && <Skeleton.Avatar size="sm" />}
<Skeleton.Base className="h-4 w-20" />
</div>
);
}
// Last column with actions (if enabled)
if (colIndex === effectiveColumns - 1 && hasActions) {
return (
<div key={`col-${colIndex}`} className="flex space-x-2 justify-end">
<Skeleton.Button size="sm" className="w-16" />
<Skeleton.Button size="sm" className="w-16" />
</div>
);
}
// Regular data columns with varied widths for realism
const widths = ['w-16', 'w-20', 'w-24', 'w-32', 'w-28'];
const widthClass = widths[colIndex % widths.length];
return (
<Skeleton.Base
key={`col-${colIndex}`}
className={`h-4 ${widthClass}`}
/>
);
})}
</div>
</div>
))}
</div>
{/* Table footer (pagination area) */}
<div className="bg-glass-bg border-t border-glass-border px-6 py-4">
<div className="flex items-center justify-between">
<Skeleton.Base className="h-4 w-32" />
<div className="flex space-x-2">
<Skeleton.Button size="sm" className="w-16" />
<Skeleton.Button size="sm" className="w-8" />
<Skeleton.Button size="sm" className="w-8" />
<Skeleton.Button size="sm" className="w-16" />
</div>
</div>
</div>
</Card>
);
};
export default TableSkeleton;