import { useId, useState } from 'react' import AnimatedCollapse from '@/components/common/AnimatedCollapse' import SortableList from '@/components/common/SortableList' import { fieldsForCounts, orderedCountFields, selectedCountChildren, selectedCountColumns, selectedCountFields } from '@/lib/counts' import { useCountsDefinition } from '@/lib/countsDefinitions' import { useClientMotion } from '@/lib/useClientMotion' import { useUITranslation } from '@/lib/useUITranslation' import type { CountField, CountsResource } from '@/lib/counts' type BranchProps = { field: CountField; path: string; enabled: boolean selected: Set; params: URLSearchParams select: (path: string, checked: boolean) => void update: (key: string, value: string) => void } const FieldBranch = ({ field, path, enabled, selected, params, select, update }: BranchProps) => { const { label, message } = useUITranslation ('counts') const [open, setOpen] = useState (false) const id = useId () const motion = useClientMotion () const checked = selected.has (path) return <>
{field.children != null && }
{field.children != null &&
} } const FieldGroup = ({ fields, path, params, enabled, selected, select, update }: { fields: CountField[]; path: string; params: URLSearchParams enabled: boolean; selected: Set; select: BranchProps['select'] update: BranchProps['update'] }, ) => { const { message } = useUITranslation ('counts') const ordered = orderedCountFields (fields, params, path) const prefix = path ? `${path}.` : '' return field.key) }} fixed={path === '' ? ['thumbnail'] : []} name={key => message ('reorder', { column: message (fields.find (field => field.key === key)!.label, fields.find (field => field.key === key)!.labelValues).text })} renderGroup={(_, content) => content} onChange={groups => { const current = fields.map (field => `${prefix}${field.key}`) const other = (params.get ('order') ?? '').split (' ') .filter (key => key && !current.includes (key)) update ('order', [...other, ...groups.items.map (key => `${prefix}${key}`)].join (' ')) }} renderItem={key => { const field = fields.find (field => field.key === key)! return }}/> } const CountsFieldTree = ( { resource, params, update, fields: suppliedFields, selectionKey = 'columns', parent = '' }: { resource: CountsResource fields?: CountField[] selectionKey?: string parent?: string params: URLSearchParams update: (key: string, value: string) => void }, ) => { const definition = useCountsDefinition () const fields = suppliedFields ?? fieldsForCounts (resource, definition) const roots = suppliedFields == null ? selectedCountColumns (resource, params, definition) : selectedCountFields (fields, params, selectionKey, parent).map (field => field.key) const selected = selectedCountChildren (params) const rootPath = (key: string) => parent ? `${parent}.${key}` : key for (const root of roots) selected.add (rootPath (root)) const select = (path: string, checked: boolean) => { const root = fields.find (field => rootPath (field.key) === path) if (root != null) { const next = new Set (roots) if (checked) next.add (root.key) else next.delete (root.key) update (selectionKey, fields.filter (field => next.has (field.key)) .map (field => field.key).join (' ')) return } if (checked) { const parts = path.split ('.') for (let index = 1; index < parts.length; ++index) selected.add (parts.slice (0, index + 1).join ('.')) } else selected.delete (path) const nextParams = new URLSearchParams (params) nextParams.set ('children', [...selected].filter (key => key.includes ('.')).join (' ')) const children = selectedCountChildren (nextParams) update ('children', [...children].join (' ')) const nextRoots = new Set (roots) const ancestor = fields.find (field => path.startsWith (`${rootPath (field.key)}.`)) if (checked && ancestor != null) nextRoots.add (ancestor.key) for (const field of fields) if (field.children != null && !field.children.some (child => children.has (`${rootPath (field.key)}.${child.key}`))) nextRoots.delete (field.key) update (selectionKey, fields.filter (field => nextRoots.has (field.key)) .map (field => field.key).join (' ')) } const visibleFields = parent === '' ? fields.filter (field => field.key !== 'thumbnail') : fields return ( <> ) } export default CountsFieldTree