import React, { useState, useEffect } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { api } from '../lib/api'
import { Loader2, Play, Square, ExternalLink } from 'lucide-react'
export const ActiveTimer = () => {
const queryClient = useQueryClient()
const [description, setDescription] = useState('')
const [isInputVisible, setIsInputVisible] = useState(false)
const [elapsed, setElapsed] = useState(0)
const { data: runningEntry, isLoading } = useQuery({
queryKey: ['running-entry'],
queryFn: () => api.getRunningTimeEntry(),
refetchInterval: 30000,
})
const startMutation = useMutation({
mutationFn: (desc: string) => api.createTimeEntry({ description, startTime: new Date().toISOString() }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['running-entry'] })
setIsInputVisible(false)
setDescription('')
},
})
const stopMutation = useMutation({
mutationFn: (id: string) => api.stopTimeEntry(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['running-entry'] })
},
})
useEffect(() => {
let interval: NodeJS.Timeout
if (runningEntry?.startTime) {
const update = () => {
const start = new Date(runningEntry.startTime).getTime()
const now = Date.now()
setElapsed(Math.floor((now - start) / 1000))
}
update()
interval = setInterval(update, 1000)
} else {
setElapsed(0)
}
return () => clearInterval(interval)
}, [runningEntry])
const formatTime = (seconds: number) => {
const h = Math.floor(seconds / 3600)
const m = Math.floor((seconds % 3600) / 60)
const s = seconds % 60
return h > 0
? `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
: `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
}
const handlePopout = () => {
window.open('/tracker-popout', 'tracker', 'width=320,height=220')
}
if (isLoading) return
if (runningEntry) {
return (
{runningEntry.description || 'No description'}
{formatTime(elapsed)}
)
}
return (
)
}
export const PopoutTrackerView = () => {
const queryClient = useQueryClient()
const [description, setDescription] = useState('')
const [isInputVisible, setIsInputVisible] = useState(false)
const [elapsed, setElapsed] = useState(0)
const { data: runningEntry, isLoading } = useQuery({
queryKey: ['running-entry'],
queryFn: () => api.getRunningTimeEntry(),
refetchInterval: 10000,
})
const startMutation = useMutation({
mutationFn: (desc: string) => api.createTimeEntry({ description, startTime: new Date().toISOString() }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['running-entry'] })
setIsInputVisible(false)
setDescription('')
},
})
const stopMutation = useMutation({
mutationFn: (id: string) => api.stopTimeEntry(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['running-entry'] })
},
})
useEffect(() => {
let interval: NodeJS.Timeout
if (runningEntry?.startTime) {
const update = () => {
const start = new Date(runningEntry.startTime).getTime()
const now = Date.now()
setElapsed(Math.floor((now - start) / 1000))
}
update()
interval = setInterval(update, 1000)
} else {
setElapsed(0)
}
return () => clearInterval(interval)
}, [runningEntry])
const formatTime = (seconds: number) => {
const h = Math.floor(seconds / 3600)
const m = Math.floor((seconds % 3600) / 60)
const s = seconds % 60
return h > 0
? `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
: `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
}
if (isLoading) return
return (
{runningEntry ? (
<>
{runningEntry.description || 'No description'}
{formatTime(elapsed)}
>
) : (
<>
No active timer
{isInputVisible ? (
) : (
)}
>
)}
)
}