'use client' import Badge from '@/app/components/base/badge' import Checkbox from '@/app/components/base/checkbox' import cn from '@/utils/classnames' import type { FC } from 'react' import { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' export type CheckboxListOption = { label: string value: string disabled?: boolean } export type CheckboxListProps = { title?: string label?: string description?: string options: CheckboxListOption[] value?: string[] onChange?: (value: string[]) => void disabled?: boolean containerClassName?: string showSelectAll?: boolean showCount?: boolean maxHeight?: string | number } const CheckboxList: FC = ({ title = '', label, description, options, value = [], onChange, disabled = false, containerClassName, showSelectAll = true, showCount = true, maxHeight, }) => { const { t } = useTranslation() const selectedCount = value.length const isAllSelected = useMemo(() => { const selectableOptions = options.filter(option => !option.disabled) return selectableOptions.length > 0 && selectableOptions.every(option => value.includes(option.value)) }, [options, value]) const isIndeterminate = useMemo(() => { const selectableOptions = options.filter(option => !option.disabled) const selectedCount = selectableOptions.filter(option => value.includes(option.value)).length return selectedCount > 0 && selectedCount < selectableOptions.length }, [options, value]) const handleSelectAll = useCallback(() => { if (disabled) return if (isAllSelected) { // Deselect all onChange?.([]) } else { // Select all non-disabled options const allValues = options .filter(option => !option.disabled) .map(option => option.value) onChange?.(allValues) } }, [isAllSelected, options, onChange, disabled]) const handleToggleOption = useCallback((optionValue: string) => { if (disabled) return const newValue = value.includes(optionValue) ? value.filter(v => v !== optionValue) : [...value, optionValue] onChange?.(newValue) }, [value, onChange, disabled]) return (
{label && (
{label}
)} {description && (
{description}
)}
{(showSelectAll || title) && (
{showSelectAll && ( )}
{title && ( {title} )} {showCount && selectedCount > 0 && ( {t('common.operation.selectCount', { count: selectedCount })} )}
)}
{!options.length ? (
{t('common.noData')}
) : ( options.map((option) => { const selected = value.includes(option.value) return (
{ if (!option.disabled && !disabled) handleToggleOption(option.value) }} > { if (!option.disabled && !disabled) handleToggleOption(option.value) }} disabled={option.disabled || disabled} />
{option.label}
) }) )}
) } export default CheckboxList