1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
6+ < title > Pushup Timer</ title >
7+ < style >
8+ body {
9+ font-family : Arial, sans-serif;
10+ display : flex;
11+ flex-direction : column;
12+ align-items : center;
13+ justify-content : center;
14+ min-height : 100vh ;
15+ margin : 0 ;
16+ background : linear-gradient (135deg , # 667eea 0% , # 764ba2 100% );
17+ color : white;
18+ }
19+
20+ .container {
21+ text-align : center;
22+ background : rgba (255 , 255 , 255 , 0.1 );
23+ padding : 40px ;
24+ border-radius : 20px ;
25+ box-shadow : 0 8px 32px rgba (0 , 0 , 0 , 0.3 );
26+ max-width : 500px ;
27+ width : 90% ;
28+ }
29+
30+ .counter {
31+ font-size : 4rem ;
32+ font-weight : bold;
33+ margin-bottom : 20px ;
34+ }
35+
36+ .phase {
37+ font-size : 2.5rem ;
38+ font-weight : bold;
39+ margin : 20px 0 ;
40+ padding : 20px ;
41+ border-radius : 15px ;
42+ transition : all 0.3s ease;
43+ }
44+
45+ .phase .down {
46+ background : # ff6b6b ;
47+ box-shadow : 0 4px 15px rgba (255 , 107 , 107 , 0.4 );
48+ }
49+
50+ .phase .hold {
51+ background : # ffd93d ;
52+ color : # 333 ;
53+ box-shadow : 0 4px 15px rgba (255 , 217 , 61 , 0.4 );
54+ }
55+
56+ .phase .up {
57+ background : # 6bcf7f ;
58+ box-shadow : 0 4px 15px rgba (107 , 207 , 127 , 0.4 );
59+ }
60+
61+ .phase .rest {
62+ background : # 4ecdc4 ;
63+ box-shadow : 0 4px 15px rgba (78 , 205 , 196 , 0.4 );
64+ }
65+
66+ .phase .countdown {
67+ background : # 9b59b6 ;
68+ box-shadow : 0 4px 15px rgba (155 , 89 , 182 , 0.4 );
69+ animation : pulse 1s infinite;
70+ }
71+
72+ @keyframes pulse {
73+ 0% { transform : scale (1 ); }
74+ 50% { transform : scale (1.05 ); }
75+ 100% { transform : scale (1 ); }
76+ }
77+
78+ .timer {
79+ font-size : 3rem ;
80+ font-weight : bold;
81+ margin : 20px 0 ;
82+ }
83+
84+ .progress-bar {
85+ width : 100% ;
86+ height : 20px ;
87+ background : rgba (255 , 255 , 255 , 0.2 );
88+ border-radius : 10px ;
89+ overflow : hidden;
90+ margin : 20px 0 ;
91+ }
92+
93+ .progress-fill {
94+ height : 100% ;
95+ background : white;
96+ transition : width 0.1s linear;
97+ }
98+
99+ .controls {
100+ margin-top : 30px ;
101+ }
102+
103+ button {
104+ font-size : 1.2rem ;
105+ padding : 15px 30px ;
106+ margin : 10px ;
107+ border : none;
108+ border-radius : 10px ;
109+ background : rgba (255 , 255 , 255 , 0.2 );
110+ color : white;
111+ cursor : pointer;
112+ transition : all 0.3s ease;
113+ }
114+
115+ button : hover {
116+ background : rgba (255 , 255 , 255 , 0.3 );
117+ transform : translateY (-2px );
118+ }
119+
120+ .completed {
121+ font-size : 2rem ;
122+ color : # 6bcf7f ;
123+ margin-top : 20px ;
124+ }
125+ </ style >
126+ </ head >
127+ < body >
128+ < div class ="container ">
129+ < div class ="counter ">
130+ Pushup < span id ="currentPushup "> 0</ span > / 15
131+ </ div >
132+
133+ < div id ="phase " class ="phase rest ">
134+ Ready to Start
135+ </ div >
136+
137+ < div class ="timer " id ="timer "> 0</ div >
138+
139+ < div class ="progress-bar ">
140+ < div class ="progress-fill " id ="progressFill "> </ div >
141+ </ div >
142+
143+ < div class ="controls ">
144+ < button onclick ="startWorkout() "> Start</ button >
145+ < button onclick ="pauseWorkout() "> Pause</ button >
146+ < button onclick ="resetWorkout() "> Reset</ button >
147+ </ div >
148+
149+ < div id ="completed " class ="completed " style ="display: none; ">
150+ 🎉 Great job! All 15 pushups completed! 🎉
151+ </ div >
152+ </ div >
153+
154+ < script >
155+ let currentPushup = 0 ;
156+ let currentPhase = 'ready' ; // ready, countdown, down, hold, up
157+ let timeLeft = 0 ;
158+ let totalTime = 0 ;
159+ let intervalId = null ;
160+ let isRunning = false ;
161+
162+ const phases = {
163+ countdown : { duration : 5 , text : 'GET READY' , class : 'countdown' } ,
164+ down : { duration : 2 , text : 'GO DOWN' , class : 'down' } ,
165+ hold : { duration : 1 , text : 'HOLD' , class : 'hold' } ,
166+ up : { duration : 1 , text : 'PUSH UP' , class : 'up' }
167+ } ;
168+
169+ function updateDisplay ( ) {
170+ document . getElementById ( 'currentPushup' ) . textContent = currentPushup ;
171+ document . getElementById ( 'timer' ) . textContent = timeLeft ;
172+
173+ const phaseElement = document . getElementById ( 'phase' ) ;
174+ const progressFill = document . getElementById ( 'progressFill' ) ;
175+
176+ if ( currentPhase === 'ready' ) {
177+ phaseElement . textContent = 'Ready to Start' ;
178+ phaseElement . className = 'phase rest' ;
179+ progressFill . style . width = '0%' ;
180+ } else if ( currentPhase === 'completed' ) {
181+ phaseElement . textContent = 'Workout Complete!' ;
182+ phaseElement . className = 'phase rest' ;
183+ progressFill . style . width = '100%' ;
184+ document . getElementById ( 'completed' ) . style . display = 'block' ;
185+ } else if ( currentPhase === 'countdown' ) {
186+ phaseElement . textContent = `GET READY - ${ timeLeft } ` ;
187+ phaseElement . className = 'phase countdown' ;
188+ const progress = ( ( totalTime - timeLeft ) / totalTime ) * 100 ;
189+ progressFill . style . width = `${ progress } %` ;
190+ } else {
191+ const phase = phases [ currentPhase ] ;
192+ phaseElement . textContent = phase . text ;
193+ phaseElement . className = `phase ${ phase . class } ` ;
194+
195+ const progress = ( ( totalTime - timeLeft ) / totalTime ) * 100 ;
196+ progressFill . style . width = `${ progress } %` ;
197+ }
198+ }
199+
200+ function nextPhase ( ) {
201+ if ( currentPhase === 'ready' ) {
202+ currentPhase = 'countdown' ;
203+ } else if ( currentPhase === 'countdown' ) {
204+ currentPushup = 1 ;
205+ currentPhase = 'down' ;
206+ } else if ( currentPhase === 'down' ) {
207+ currentPhase = 'hold' ;
208+ } else if ( currentPhase === 'hold' ) {
209+ currentPhase = 'up' ;
210+ } else if ( currentPhase === 'up' ) {
211+ if ( currentPushup >= 15 ) {
212+ currentPhase = 'completed' ;
213+ clearInterval ( intervalId ) ;
214+ isRunning = false ;
215+ updateDisplay ( ) ;
216+ return ;
217+ } else {
218+ currentPushup ++ ;
219+ currentPhase = 'down' ;
220+ }
221+ }
222+
223+ timeLeft = phases [ currentPhase ] . duration ;
224+ totalTime = timeLeft ;
225+ updateDisplay ( ) ;
226+ }
227+
228+ function tick ( ) {
229+ timeLeft -- ;
230+ updateDisplay ( ) ;
231+
232+ if ( timeLeft <= 0 ) {
233+ nextPhase ( ) ;
234+ }
235+ }
236+
237+ function startWorkout ( ) {
238+ if ( ! isRunning ) {
239+ if ( currentPhase === 'ready' ) {
240+ nextPhase ( ) ;
241+ }
242+ intervalId = setInterval ( tick , 1000 ) ;
243+ isRunning = true ;
244+ }
245+ }
246+
247+ function pauseWorkout ( ) {
248+ if ( isRunning ) {
249+ clearInterval ( intervalId ) ;
250+ isRunning = false ;
251+ }
252+ }
253+
254+ function resetWorkout ( ) {
255+ clearInterval ( intervalId ) ;
256+ isRunning = false ;
257+ currentPushup = 0 ;
258+ currentPhase = 'ready' ;
259+ timeLeft = 0 ;
260+ totalTime = 0 ;
261+ document . getElementById ( 'completed' ) . style . display = 'none' ;
262+ updateDisplay ( ) ;
263+ }
264+
265+ // Initialize display
266+ updateDisplay ( ) ;
267+ </ script >
268+ </ body >
269+ </ html >
0 commit comments