1+ import { useEffect , useState } from "react" ;
2+ import { Task , Category } from "@/types/task" ;
3+ import { Square } from "lucide-react" ;
4+ import { Button } from "@/components/ui/button" ;
5+
6+ interface CurrentTaskFooterProps {
7+ currentTask : Task | null ;
8+ categories : Category [ ] ;
9+ onTaskTimer : ( taskId : string , action : "start" | "stop" | "complete" ) => void ;
10+ }
11+
12+ export const CurrentTaskFooter = ( {
13+ currentTask,
14+ categories,
15+ onTaskTimer,
16+ } : CurrentTaskFooterProps ) => {
17+ const [ currentTime , setCurrentTime ] = useState ( new Date ( ) ) ;
18+ const [ elapsedTime , setElapsedTime ] = useState ( 0 ) ;
19+
20+ // 1秒ごとに現在時刻を更新
21+ useEffect ( ( ) => {
22+ const timer = setInterval ( ( ) => {
23+ setCurrentTime ( new Date ( ) ) ;
24+ } , 1000 ) ;
25+
26+ return ( ) => clearInterval ( timer ) ;
27+ } , [ ] ) ;
28+
29+ // 経過時間を計算
30+ useEffect ( ( ) => {
31+ if ( currentTask ?. start_time ) {
32+ const startTime = new Date ( currentTask . start_time ) ;
33+ const elapsed = Math . floor ( ( currentTime . getTime ( ) - startTime . getTime ( ) ) / 1000 ) ;
34+ setElapsedTime ( elapsed ) ;
35+ } else {
36+ setElapsedTime ( 0 ) ;
37+ }
38+ } , [ currentTask ?. start_time , currentTime ] ) ;
39+
40+ // 経過時間をフォーマット
41+ const formatElapsedTime = ( seconds : number ) => {
42+ const hours = Math . floor ( seconds / 3600 ) ;
43+ const minutes = Math . floor ( ( seconds % 3600 ) / 60 ) ;
44+ const secs = seconds % 60 ;
45+
46+ if ( hours > 0 ) {
47+ return `${ hours } :${ minutes . toString ( ) . padStart ( 2 , "0" ) } :${ secs . toString ( ) . padStart ( 2 , "0" ) } ` ;
48+ }
49+ return `${ minutes } :${ secs . toString ( ) . padStart ( 2 , "0" ) } ` ;
50+ } ;
51+
52+ if ( ! currentTask ) {
53+ return null ;
54+ }
55+
56+ const category = categories . find ( ( cat ) => cat . id === currentTask . category_id ) ;
57+ const categoryColor = category ?. color || "#6b7280" ;
58+
59+ return (
60+ < div
61+ className = "fixed bottom-0 left-0 right-0 bg-white border-t shadow-lg p-4 z-50"
62+ style = { { borderTopColor : categoryColor } }
63+ >
64+ < div className = "max-w-4xl mx-auto flex items-center justify-between" >
65+ < div className = "flex items-center gap-4" >
66+ < div
67+ className = "w-3 h-3 rounded-full animate-pulse"
68+ style = { { backgroundColor : categoryColor } }
69+ />
70+ < div >
71+ < p className = "font-medium text-gray-900" > { currentTask . title } </ p >
72+ < div className = "flex items-center gap-2 text-sm text-gray-600" >
73+ { category && (
74+ < span style = { { color : categoryColor } } >
75+ { category . name }
76+ </ span >
77+ ) }
78+ < span > •</ span >
79+ < span > 開始: { new Date ( currentTask . start_time ! ) . toLocaleTimeString ( "ja-JP" , {
80+ hour : "2-digit" ,
81+ minute : "2-digit"
82+ } ) } </ span >
83+ </ div >
84+ </ div >
85+ </ div >
86+
87+ < div className = "flex items-center gap-4" >
88+ < div className = "text-right" >
89+ < p className = "text-2xl font-mono font-bold" style = { { color : categoryColor } } >
90+ { formatElapsedTime ( elapsedTime ) }
91+ </ p >
92+ < p className = "text-xs text-gray-500" > 経過時間</ p >
93+ </ div >
94+
95+ < Button
96+ size = "sm"
97+ variant = "outline"
98+ onClick = { ( ) => onTaskTimer ( currentTask . id , "stop" ) }
99+ className = "hover:bg-red-50"
100+ style = { {
101+ color : "#dc2626" ,
102+ borderColor : "#dc2626" ,
103+ } }
104+ >
105+ < Square className = "h-4 w-4 mr-1" />
106+ 停止
107+ </ Button >
108+ </ div >
109+ </ div >
110+ </ div >
111+ ) ;
112+ } ;
0 commit comments