88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { addMonths, subMonths } from 'date-fns'
|
|
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
|
|
import { DateTime as LuxonDateTime } from 'luxon'
|
|
import { useSearchParams } from 'react-router'
|
|
|
|
import { TZ } from '@/conf'
|
|
import { DateTime } from '@repo/ui/components/datetime'
|
|
import { Badge } from '@repo/ui/components/ui/badge'
|
|
import { Button } from '@repo/ui/components/ui/button'
|
|
import { ButtonGroup } from '@repo/ui/components/ui/button-group'
|
|
|
|
import { billingPeriod, formatDate } from './util'
|
|
|
|
type RangePeriodProps = {
|
|
startDate: Date
|
|
endDate: Date
|
|
billingDay: number
|
|
}
|
|
|
|
const dtOptions: Intl.DateTimeFormatOptions = {
|
|
year: '2-digit',
|
|
hour: undefined,
|
|
minute: undefined
|
|
}
|
|
|
|
export function RangePeriod({
|
|
startDate,
|
|
endDate,
|
|
billingDay
|
|
}: RangePeriodProps) {
|
|
const today = LuxonDateTime.now().setZone(TZ).toJSDate()
|
|
const [, setSearchParams] = useSearchParams()
|
|
const prevPeriod = billingPeriod(billingDay, subMonths(startDate, 1))
|
|
const nextPeriod = billingPeriod(billingDay, addMonths(startDate, 1))
|
|
const [nextDate] = nextPeriod
|
|
|
|
return (
|
|
<>
|
|
<ButtonGroup className="max-lg:w-full">
|
|
<Button
|
|
variant="outline"
|
|
className="border-dashed cursor-pointer"
|
|
onClick={() => {
|
|
setSearchParams((searchParams) => {
|
|
const [start, end] = prevPeriod
|
|
searchParams.set('start', formatDate(start))
|
|
searchParams.set('end', formatDate(end))
|
|
return searchParams
|
|
})
|
|
}}
|
|
>
|
|
<ChevronLeftIcon />
|
|
</Button>
|
|
|
|
<Button
|
|
variant="outline"
|
|
className="pointer-events-none border-dashed flex-1"
|
|
>
|
|
<div className="gap-1 flex">
|
|
<Badge variant="outline" className="rounded-sm px-1 font-mono">
|
|
<DateTime options={dtOptions}>{startDate}</DateTime>
|
|
</Badge>
|
|
<Badge variant="outline" className="rounded-sm px-1 font-mono">
|
|
<DateTime options={dtOptions}>{endDate}</DateTime>
|
|
</Badge>
|
|
</div>
|
|
</Button>
|
|
|
|
<Button
|
|
variant="outline"
|
|
className="border-dashed cursor-pointer"
|
|
disabled={nextDate > today}
|
|
onClick={() => {
|
|
setSearchParams((searchParams) => {
|
|
const [start, end] = nextPeriod
|
|
searchParams.set('start', formatDate(start))
|
|
searchParams.set('end', formatDate(end))
|
|
return searchParams
|
|
})
|
|
}}
|
|
>
|
|
<ChevronRightIcon />
|
|
</Button>
|
|
</ButtonGroup>
|
|
</>
|
|
)
|
|
}
|