| 1 | 'use client' |
| 2 | |
| 3 | import { useRouter } from '@bprogress/next/app' |
| 4 | import { Check, Pause |
| 5 | import { usePathname } |
| 6 | import { useEffect, useState |
| 7 | import { Button } |
| 8 | import { |
| 9 | elapsedMinutesFromMs, |
| 10 | formatElapsedMs, |
| 11 | getElapsedMs, |
| 12 | useTimerStore, |
| 13 | } from '@/stores/timer-store' |
| 14 | |
| 15 | export function FloatingTimer() |
| 16 | const { startedAt, |
| 17 | useTimerStore((s) |
| 18 | const router = |
| 19 | const pathname = |
| 20 | const [now, |
| 21 | |
| 22 | const isActive = |
| 23 | const isRunning = |
| 24 | |
| 25 | useEffect(() => |
| 26 | if (!isRunning) |
| 27 | return |
| 28 | } |
| 29 | const id = |
| 30 | return () => |
| 31 | }, [isRunning]) |
| 32 | |
| 33 | if (!(isActive |
| 34 | return null |
| 35 | } |
| 36 | |
| 37 | const elapsedMs = |
| 38 | const timesheetsPath = |
| 39 | const isOnTimesheetsPage = |
| 40 | |
| 41 | const handleLog = |
| 42 | const minutes = |
| 43 | stop() |
| 44 | if (isOnTimesheetsPage) { |
| 45 | window.dispatchEvent( |
| 46 | new CustomEvent('timer:log |
| 47 | ) |
| 48 | } else { |
| 49 | router.push(`${ |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | return ( |
| 54 | <div className='fixed right-4 bottom-4 z-50 flex items-center gap-3 rounded-lg border bg-background px-3 py-2 shadow-lg |
| 55 | <div className='flex flex-col |
| 56 | <span className='text-muted-foreground text-xs |
| 57 | {context.projectName} |
| 58 | {isRunning ? '' |
| 59 | </span> |
| 60 | <span className='font-mono font-semibold text-sm tabular-nums |
| 61 | {formatElapsedMs(elapsedMs)} |
| 62 | </span> |
| 63 | </div> |
| 64 | {isRunning ? ( |
| 65 | <Button onClick={ |
| 66 | <Pause className=' |
| 67 | Pause |
| 68 | </Button> |
| 69 | ) : ( |
| 70 | <> |
| 71 | <Button onClick={ |
| 72 | <Play className=' |
| 73 | Resume |
| 74 | </Button> |
| 75 | <Button onClick={ |
| 76 | <Check className=' |
| 77 | Log Time |
| 78 | </Button> |
| 79 | </> |
| 80 | )} |
| 81 | </div> |
| 82 | ) |
| 83 | } |