import { useState } from 'react'; import { Group, TextInput, Button, Text, NumberInput, Flex } from '@mantine/core'; import LocalIcon from '../shared/LocalIcon'; import { Tooltip } from '../shared/Tooltip'; import { usePageSelectionTips } from '../tooltips/usePageSelectionTips'; import classes from './BulkSelectionPanel.module.css'; import { appendExpression, insertOperatorSmart, firstNExpression, lastNExpression, everyNthExpression, rangeExpression, } from './BulkSelection'; interface BulkSelectionPanelProps { csvInput: string; setCsvInput: (value: string) => void; selectedPageIds: string[]; displayDocument?: { pages: { id: string; pageNumber: number }[] }; onUpdatePagesFromCSV: (override?: string) => void; } const BulkSelectionPanel = ({ csvInput, setCsvInput, selectedPageIds, displayDocument, onUpdatePagesFromCSV, }: BulkSelectionPanelProps) => { const pageSelectionTips = usePageSelectionTips(); const [advancedOpened, setAdvancedOpened] = useState(false); const [firstNValue, setFirstNValue] = useState(''); const [lastNValue, setLastNValue] = useState(''); const [everyNthValue, setEveryNthValue] = useState(''); const [rangeStart, setRangeStart] = useState(''); const [rangeEnd, setRangeEnd] = useState(''); const [firstNError, setFirstNError] = useState(null); const [lastNError, setLastNError] = useState(null); const [rangeError, setRangeError] = useState(null); const maxPages = displayDocument?.pages?.length ?? 0; const applyExpression = (expr: string) => { const nextInput = appendExpression(csvInput, expr); setCsvInput(nextInput); onUpdatePagesFromCSV(nextInput); }; const handleNone = () => { setCsvInput(''); onUpdatePagesFromCSV(); setFirstNValue(''); setLastNValue(''); setEveryNthValue(''); }; const insertOperator = (op: 'and' | 'or' | 'not') => { const next = insertOperatorSmart(csvInput, op); setCsvInput(next); }; return ( <> { const next = e.target.value; setCsvInput(next); onUpdatePagesFromCSV(next); }} placeholder="1,3,5-10" rightSection={ csvInput && ( ) } label={ e.stopPropagation()} align="center" gap="xs" my="sm"> Page Selection } onBlur={() => onUpdatePagesFromCSV()} onKeyDown={(e) => e.key === 'Enter' && onUpdatePagesFromCSV()} className={classes.textInput} /> {/* Selected pages container */} {selectedPageIds.length > 0 && (
Selected: {selectedPageIds.length} pages ({displayDocument ? selectedPageIds.map(id => { const page = displayDocument.pages.find(p => p.id === id); return page?.pageNumber || 0; }).filter(n => n > 0).join(', ') : ''})
)} {/* Advanced button */}
{/* Advanced section */} {advancedOpened && (
Advanced Selection
{/* First N Pages - Card Style */}
First N Pages {firstNError && ({firstNError})}
Number of pages: { const next = typeof val === 'number' ? val : ''; setFirstNValue(next); if (next === '') setFirstNError(null); else if (typeof next === 'number' && next <= 0) setFirstNError('Enter a positive number'); else setFirstNError(null); }} min={1} placeholder="10" className={classes.fullWidthInput} error={Boolean(firstNError)} />
{/* Range - Card Style */}
Range {rangeError && ({rangeError})}
From: { const next = typeof val === 'number' ? val : ''; setRangeStart(next); const s = typeof next === 'number' ? next : null; const e = typeof rangeEnd === 'number' ? rangeEnd : null; if (s !== null && s <= 0) setRangeError('Values must be positive'); else if (s !== null && e !== null && s > e) setRangeError('From must be less than or equal to To'); else setRangeError(null); }} min={1} placeholder="5" error={Boolean(rangeError)} />
To: { const next = typeof val === 'number' ? val : ''; setRangeEnd(next); const e = typeof next === 'number' ? next : null; const s = typeof rangeStart === 'number' ? rangeStart : null; if (e !== null && e <= 0) setRangeError('Values must be positive'); else if (s !== null && e !== null && s > e) setRangeError('From must be less than or equal to To'); else setRangeError(null); }} min={1} placeholder="10" error={Boolean(rangeError)} />
{/* Last N Pages - Card Style */}
Last N Pages {lastNError && ({lastNError})}
Number of pages: { const next = typeof val === 'number' ? val : ''; setLastNValue(next); if (next === '') setLastNError(null); else if (typeof next === 'number' && next <= 0) setLastNError('Enter a positive number'); else setLastNError(null); }} min={1} placeholder="10" className={classes.fullWidthInput} error={Boolean(lastNError)} />
{/* Every Nth Page - Card Style */}
Every Nth Page
Step size: setEveryNthValue(typeof val === 'number' ? val : '')} min={1} placeholder="5" className={classes.fullWidthInput} />
Add Operators:
)} ); }; export default BulkSelectionPanel;