feat(new-tool): added chronometer
This commit is contained in:
		
							parent
							
								
									1c7257eeb0
								
							
						
					
					
						commit
						130031c225
					
				
							
								
								
									
										12
									
								
								src/tools/chronometer/chronometer.service.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/chronometer/chronometer.service.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| import { describe, expect, it } from 'vitest'; | ||||
| import { formatChronometerTime } from './chronometer.service'; | ||||
| 
 | ||||
| describe('chronometer', () => { | ||||
|   describe('formatChronometerTime', () => { | ||||
|     it('format the elapsed time', () => { | ||||
|       expect(formatChronometerTime({ elapsed: 123456 })).toEqual('02:03.456'); | ||||
|       expect(formatChronometerTime({ elapsed: 123456, msPerUnit: 100 })).toEqual('03:25:45.600'); | ||||
|       expect(formatChronometerTime({ elapsed: 12345600 })).toEqual('03:25:45.600'); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										13
									
								
								src/tools/chronometer/chronometer.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/tools/chronometer/chronometer.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| export function formatChronometerTime({ elapsed, msPerUnit = 1 }: { elapsed: number; msPerUnit?: number }) { | ||||
|   const elapsedMs = elapsed * msPerUnit; | ||||
| 
 | ||||
|   const ms = elapsedMs % 1000; | ||||
|   const secs = ((elapsedMs - ms) / 1000) % 60; | ||||
|   const mins = (((elapsedMs - ms) / 1000 - secs) / 60) % 60; | ||||
|   const hrs = (((elapsedMs - ms) / 1000 - secs) / 60 - mins) / 60; | ||||
|   const hrsString = hrs > 0 ? `${hrs.toString().padStart(2, '0')}:` : ''; | ||||
| 
 | ||||
|   return `${hrsString}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${ms | ||||
|     .toString() | ||||
|     .padStart(3, '0')}`;
 | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/tools/chronometer/chronometer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/tools/chronometer/chronometer.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <n-card> | ||||
|       <div class="duration">{{ formatChronometerTime({ elapsed: counter, msPerUnit }) }}</div> | ||||
|     </n-card> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button v-if="!isActive" secondary type="primary" @click="resume">Start</n-button> | ||||
|       <n-button v-else secondary type="warning" @click="pause">Stop</n-button> | ||||
| 
 | ||||
|       <n-button secondary @click="counter = 0">Reset</n-button> | ||||
|     </n-space> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useInterval } from '@vueuse/core'; | ||||
| import { formatChronometerTime } from './chronometer.service'; | ||||
| 
 | ||||
| const msPerUnit = 10; | ||||
| 
 | ||||
| const { counter, pause, resume, isActive } = useInterval(msPerUnit, { controls: true, immediate: false }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
| .duration { | ||||
|   text-align: center; | ||||
|   font-size: 40px; | ||||
|   font-family: monospace; | ||||
|   margin: 20px 0; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										11
									
								
								src/tools/chronometer/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/tools/chronometer/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| import { TimerOutlined } from '@vicons/material'; | ||||
| import { defineTool } from '../tool'; | ||||
| 
 | ||||
| export const tool = defineTool({ | ||||
|   name: 'Chronometer', | ||||
|   path: '/chronometer', | ||||
|   description: 'Monitor the duration of a thing. Basically a chronometer with simple chronometer features.', | ||||
|   keywords: ['chronometer', 'time', 'lap', 'duration', 'measure', 'pause', 'resume', 'stopwatch'], | ||||
|   component: () => import('./chronometer.vue'), | ||||
|   icon: TimerOutlined, | ||||
| }); | ||||
| @ -5,6 +5,7 @@ import { tool as base64Converter } from './base64-converter'; | ||||
| import { tool as bcrypt } from './bcrypt'; | ||||
| import { tool as bip39 } from './bip39-generator'; | ||||
| import { tool as caseConverter } from './case-converter'; | ||||
| import { tool as chronometer } from './chronometer'; | ||||
| import { tool as colorConverter } from './color-converter'; | ||||
| import { tool as crontabGenerator } from './crontab-generator'; | ||||
| import { tool as dateTimeConverter } from './date-time-converter'; | ||||
| @ -59,6 +60,11 @@ export const toolsByCategory: ToolCategory[] = [ | ||||
|     icon: LockOpen, | ||||
|     components: [mathEvaluator], | ||||
|   }, | ||||
|   { | ||||
|     name: 'Measurement', | ||||
|     icon: LockOpen, | ||||
|     components: [chronometer], | ||||
|   }, | ||||
|   { | ||||
|     name: 'Text', | ||||
|     icon: LockOpen, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user