import { useEffect, useRef, useState, type ReactNode } from 'react'
import type { ClaudeConfigSelector, DateRange } from '../lib/types'
import { Dropdown } from './Dropdown'
import { ProviderPop, type ProviderOption } from './ProviderPop'
import { RangeCalendar } from './RangeCalendar'
import { SegTabs, type SegOption } from './SegTabs'
/** Sentinel option value: no --claude-config-source flag (aggregate all configs). */
const ALL_CONFIGS = ''
/** The real CLI period vocabulary (`codeburn ... --period`, src/cli-date.ts). */
export const PERIOD_OPTIONS: SegOption[] = [
{ value: 'today', label: 'Today' },
{ value: 'week', label: '7D' },
{ value: '30days', label: '30D' },
{ value: 'month', label: 'Month' },
{ value: 'all', label: '6M' },
{ value: 'lifetime', label: 'Life' },
]
/** The `.bar` top bar: title, scope caption, period SegTabs, provider ProviderPop. */
export function TopBar({
title,
scope,
period,
onPeriodChange,
customRange,
onRangeSelect,
provider,
providerLabel,
providerOptions,
onProviderSelect,
claudeConfigs,
configSource,
onConfigSelect,
}: {
title: ReactNode
scope?: ReactNode
period: string
onPeriodChange: (value: string) => void
customRange: DateRange | null
onRangeSelect: (range: DateRange) => void
provider: string
providerLabel: string
providerOptions: ProviderOption[]
onProviderSelect: (value: string) => void
claudeConfigs?: ClaudeConfigSelector
configSource: string | null
onConfigSelect: (id: string) => void
}) {
return (
{title}
{scope !== undefined &&
{scope}}
{claudeConfigs &&
}
)
}
/** Claude config source switcher. Only getOverview honors the selection, so the
* footer names the limit; the active label is also echoed in the scope line. */
function ConfigPicker({ configs, value, onSelect }: { configs: ClaudeConfigSelector; value: string | null; onSelect: (id: string) => void }) {
const options = [
{ value: ALL_CONFIGS, label: 'All Claude configs' },
...configs.options.map(option => ({ value: option.id, label: option.label })),
]
return (
)
}
function formatRange(range: DateRange): string {
const from = new Date(`${range.from}T12:00:00`)
const to = new Date(`${range.to}T12:00:00`)
const sameYear = from.getFullYear() === to.getFullYear()
const sameMonth = sameYear && from.getMonth() === to.getMonth()
const left = from.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: sameYear ? undefined : 'numeric' })
const right = to.toLocaleDateString('en-US', { month: sameMonth ? undefined : 'short', day: 'numeric', year: sameYear ? undefined : 'numeric' })
return `${left} – ${right}`
}
export function rangeLabel(range: DateRange): string {
return formatRange(range)
}
function CalendarPop({ value, onSelect }: { value: DateRange | null; onSelect: (range: DateRange) => void }) {
const [open, setOpen] = useState(false)
const wrapRef = useRef(null)
useEffect(() => {
if (!open) return
const onPointerDown = (event: MouseEvent) => {
if (!wrapRef.current?.contains(event.target as Node)) setOpen(false)
}
const onKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') setOpen(false)
}
document.addEventListener('mousedown', onPointerDown)
document.addEventListener('keydown', onKeyDown)
return () => {
document.removeEventListener('mousedown', onPointerDown)
document.removeEventListener('keydown', onKeyDown)
}
}, [open])
const label = value ? formatRange(value) : 'Choose date range'
return (
{open && (
{
onSelect(range)
setOpen(false)
}}
/>
)}
)
}