111 lines
3.9 KiB
TypeScript
111 lines
3.9 KiB
TypeScript
import chalk from 'chalk';
|
|
import dayjs, { Dayjs } from 'dayjs';
|
|
import * as readline from 'readline/promises';
|
|
import { formatDuration, formatTimestamp, getHoursRoundedStr } from './format.js';
|
|
import { Duration } from 'dayjs/plugin/duration';
|
|
import { parseDuration, parseTimestamp } from './parse.js';
|
|
|
|
const { log, error } = console;
|
|
const defaultStartTime = '08:00';
|
|
const lunchBreakDuration = dayjs.duration(30, 'minutes');
|
|
const defaultWorkDayDuration = dayjs.duration({ hours: 7, minutes: 30 });
|
|
|
|
const main = async () => {
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout,
|
|
});
|
|
|
|
let started: Dayjs | undefined = undefined;
|
|
|
|
try {
|
|
// Get work day duration
|
|
let workDayDuration: Duration | undefined = undefined;
|
|
|
|
const durationAnswer = await rl.question(
|
|
`How long is your work day today, excluding the lunch break? [${defaultWorkDayDuration.format('HH:mm')}] `,
|
|
);
|
|
if (durationAnswer !== '') {
|
|
workDayDuration = parseDuration(durationAnswer);
|
|
if (workDayDuration.asMinutes() <= 0) {
|
|
error(
|
|
chalk.red(
|
|
`Failed to parse ${durationAnswer} to duration, using default work day duration ${defaultWorkDayDuration}`,
|
|
),
|
|
);
|
|
workDayDuration = undefined;
|
|
}
|
|
}
|
|
|
|
if (!workDayDuration) {
|
|
workDayDuration = defaultWorkDayDuration;
|
|
}
|
|
|
|
// Calculate worked time
|
|
const startTimeAnswer = await rl.question(`What time did you start work today? [${defaultStartTime}] `);
|
|
if (startTimeAnswer !== '') {
|
|
started = parseTimestamp(startTimeAnswer);
|
|
if (!started.isValid()) {
|
|
error(
|
|
chalk.red(
|
|
`Failed to parse ${startTimeAnswer} to time, using default start time ${defaultStartTime}`,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!started?.isValid()) {
|
|
started = parseTimestamp(defaultStartTime);
|
|
}
|
|
|
|
let stopped: Dayjs | undefined = undefined;
|
|
const stoppedAnswer = await rl.question(
|
|
"What time did you stop working (leave empty if you didn't stop yet)? ",
|
|
);
|
|
|
|
if (stoppedAnswer === '') {
|
|
stopped = dayjs();
|
|
} else {
|
|
stopped = parseTimestamp(stoppedAnswer);
|
|
if (!stopped.isValid()) {
|
|
error(`Failed to parse ${stoppedAnswer} to time, using current time`);
|
|
stopped = dayjs();
|
|
}
|
|
}
|
|
|
|
let worked = dayjs.duration(stopped.diff(started));
|
|
|
|
const lunchAnswer = await rl.question('Did you have a lunch break? [Y/n] ');
|
|
if (lunchAnswer.toLowerCase() !== 'n') {
|
|
worked = worked.subtract(lunchBreakDuration);
|
|
}
|
|
|
|
// Calculate unlogged time
|
|
let unLogged: Duration | undefined = undefined;
|
|
let loggedAnswer = await rl.question('How many hours did you log already? [00:00] ');
|
|
if (loggedAnswer === '') {
|
|
loggedAnswer = '00:00';
|
|
}
|
|
const logged = parseDuration(loggedAnswer);
|
|
const unLoggedDuration = workDayDuration.subtract(logged);
|
|
if (unLoggedDuration.asMinutes() > 0) {
|
|
unLogged = unLoggedDuration;
|
|
}
|
|
|
|
// Log result
|
|
log();
|
|
log('Started working at', formatTimestamp(started));
|
|
log('Stopped working at', formatTimestamp(stopped));
|
|
log('Total worked today:', chalk.green(formatDuration(worked)), chalk.yellow(getHoursRoundedStr(worked)));
|
|
log(
|
|
'Unlogged today:',
|
|
unLogged
|
|
? `${chalk.red(formatDuration(unLogged))} ${chalk.yellow(getHoursRoundedStr(unLogged))}`
|
|
: chalk.green('none'),
|
|
);
|
|
} finally {
|
|
rl.close();
|
|
}
|
|
};
|
|
|
|
main();
|