import { MouseEvent , useMemo , useRef , useState } from 'react' ; import { c } from 'ttag' ; import { getISOWeek } from 'date-fns' ; import { classnames } from '../../helpers' ; import { Tooltip } from '../tooltip' ; const getWeekNumberToMondayMap = ( days ) => { const firstMondayIndex = days . findIndex ( ( day ) => day . getDay ( ) === 1 ) ; const result = { } ; if ( firstMondayIndex === - 1 ) { return result ; } for ( let i = 0 ; i < Math . floor ( days . length / 7 ) ; i ++ ) { const day = days [ firstMondayIndex + 7 * i ] ; result [ getISOWeek ( day ) ] = day ; } return result ; } ; const getTargetMonday = ( target , weekNumberToMondayMap ) => { const idx = parseInt ( target ?. dataset ?. i || '' , 10 ) ; if ( idx >= 0 && idx <= 53 ) { return weekNumberToMondayMap [ idx ] ; } } ; const getMonday = ( days , start , end ) => { for ( let i = start ; i < end ; ++ i ) { const day = days [ i ] ; if ( day && day . getDay ( ) === 1 ) { return day ; } } } ; export interface Props { days : Date [ ] ; numberOfWeeks : number ; onClickWeekNumber ? : ( monday : Date ) => void ; onSelectWeekRange ? : ( arg : [ Date , Date ] ) => void ; } const WeekNumbers = ( { days , numberOfWeeks , onClickWeekNumber , onSelectWeekRange } ) => { const style = { '--week-count' : numberOfWeeks + 1 , } ; const weekNumberToMondayMap = useMemo ( ( ) => getWeekNumberToMondayMap ( days ) , days ) ; const [ temporaryWeekRange , setTemporaryWeekRange ] = useState < [ Date , Date | undefined ] | undefined > ( undefined ) ; const rangeStartRef = useRef < Date | undefined > ( undefined ) ; const rangeEndRef = useRef < Date | undefined > ( undefined ) ; const handleMouseDown = ( { target } ) => { const targetMonday = getTargetMonday ( target , weekNumberToMondayMap ) ; if ( rangeStartRef . current || ! targetMonday || ! onSelectWeekRange ) { return ; } setTemporaryWeekRange ( [ targetMonday , undefined ] ) ; rangeStartRef . current = targetMonday ; const handleMouseUp = ( ) => { if ( rangeEndRef . current && rangeStartRef . current ) { onSelectWeekRange ( rangeEndRef . current > rangeStartRef . current ? [ rangeStartRef . current , rangeEndRef . current ] : [ rangeEndRef . current , rangeStartRef . current ] ) ; } setTemporaryWeekRange ( undefined ) ; rangeStartRef . current = undefined ; rangeEndRef . current = undefined ; document . removeEventListener ( 'mouseup' , handleMouseUp ) ; } ; document . addEventListener ( 'mouseup' , handleMouseUp ) ; } ; const handleMouseOver = ( { target } ) => { const targetMonday = getTargetMonday ( target , weekNumberToMondayMap ) ; if ( ! rangeStartRef . current || ! targetMonday || ! onSelectWeekRange ) { return ; } rangeEndRef . current = targetMonday ; setTemporaryWeekRange ( targetMonday > rangeStartRef . current ? [ rangeStartRef . current , targetMonday ] : [ targetMonday , rangeStartRef . current ] ) ; } ; const handleFocus = ( ) => { } ; const weekNumberLabels = useMemo ( ( ) => { return Array . from ( { length : numberOfWeeks } , ( a , i ) => { const idx = i * 7 ; const monday = getMonday ( days , idx , idx + 7 ) || days [ idx ] ; const weekNumber = getISOWeek ( monday ) ; return { monday , weekNumber , } ; } ) ; } , [ days ] ) ; return ( < ul className = { classnames ( [ 'minicalendar-weeknumbers unstyled m0 text-center' , ! onSelectWeekRange && 'no-pointer-events-children' , ] ) } style = { style } onMouseDown = { handleMouseDown } onMouseOver = { handleMouseOver } onFocus = { handleFocus } > < li > < span className = "sr-only" > { c ( 'Info' ) . t `Week` } < /span> < /li> { weekNumberLabels . map ( ( { monday , weekNumber } ) => { const isPressed = ! temporaryWeekRange ? false : monday >= temporaryWeekRange [ 0 ] && monday <= ( temporaryWeekRange [ 1 ] || temporaryWeekRange [ 0 ] ) ; return ( < li key = { + monday } > < Tooltip title = { `${ c ( 'Info' ) . t `Week` } ${ weekNumber }` } originalPlacement = "bottom" > < button data - i = { weekNumber } aria - pressed = { isPressed } type = "button" className = { classnames ( [ 'minicalendar-weeknumber' , ! onClickWeekNumber && 'no-pointer-events' , ] ) } onClick = { ( ) => onClickWeekNumber ?. ( monday ) } > < span className = "no-pointer-events" > { weekNumber } < /span> < /button> < /Tooltip> < /li>); } ) } < /ul>); } ; export default WeekNumbers ;