wulf-pulse/components/admin/EntitySelector.tsx

98 lines
2.7 KiB
TypeScript
Raw Normal View History

/**
* Entity Selector Component
* Checkbox grid for selecting entities to sync
*/
'use client';
import { EntityType } from '@/lib/types/sync';
import { getEntityDisplayName } from '@/lib/utils/sync-helpers';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
interface EntitySelectorProps {
selectedEntities: EntityType[];
onChange: (entities: EntityType[]) => void;
disabled?: boolean;
}
const ALL_ENTITIES: EntityType[] = [
EntityType.COMPANIES,
EntityType.RESOURCES,
EntityType.STATUSES,
EntityType.ISSUE_TYPES,
EntityType.SUB_ISSUE_TYPES,
EntityType.WORK_TYPES,
EntityType.CONTACTS,
EntityType.PROJECTS,
EntityType.TICKETS,
EntityType.TASKS,
EntityType.CONFIGURATION_ITEMS,
EntityType.CONTRACTS,
EntityType.BILLING_ITEMS,
EntityType.TIME_ENTRIES,
];
export default function EntitySelector({
selectedEntities,
onChange,
disabled = false,
}: EntitySelectorProps) {
const handleToggle = (entity: EntityType) => {
if (selectedEntities.includes(entity)) {
onChange(selectedEntities.filter(e => e !== entity));
} else {
onChange([...selectedEntities, entity]);
}
};
const handleSelectAll = () => {
if (selectedEntities.length === ALL_ENTITIES.length) {
onChange([]);
} else {
onChange([...ALL_ENTITIES]);
}
};
const allSelected = selectedEntities.length === ALL_ENTITIES.length;
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<Label className="text-base font-semibold">Select Entities</Label>
<button
type="button"
onClick={handleSelectAll}
disabled={disabled}
className="text-sm text-primary hover:underline disabled:opacity-50"
>
{allSelected ? 'Deselect All' : 'Select All'}
</button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 md:gap-4">
{ALL_ENTITIES.map((entity) => (
<div key={entity} className="flex items-center space-x-2">
<Checkbox
id={entity}
checked={selectedEntities.includes(entity)}
onCheckedChange={() => handleToggle(entity)}
disabled={disabled}
/>
<Label
htmlFor={entity}
className="text-sm font-normal cursor-pointer"
>
{getEntityDisplayName(entity)}
</Label>
</div>
))}
</div>
<div className="text-sm text-muted-foreground">
{selectedEntities.length} of {ALL_ENTITIES.length} entities selected
</div>
</div>
);
}