UNPKG

@latentsearch/timemachine-cli

Version:

CLI tool for TimeMachine API. Generates time entries, lists users/projects, and features an enhanced dry-run output for generation.

157 lines (156 loc) 6.52 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEntry = createEntry; const chalk_1 = __importDefault(require("chalk")); const inquirer_1 = __importDefault(require("inquirer")); const inquirer_datepicker_prompt_1 = __importDefault(require("inquirer-datepicker-prompt")); const ora_1 = __importDefault(require("ora")); const luxon_1 = require("luxon"); const api_client_1 = require("../utils/api-client"); // Register the datepicker prompt type inquirer_1.default.registerPrompt("datepicker", inquirer_datepicker_prompt_1.default); /** * Creates a time entry interactively */ async function createEntry(options) { try { const api = (0, api_client_1.createApiClient)(options); // Fetch users and projects first for selection console.log(chalk_1.default.blue("Fetching users and projects...")); const spinner = (0, ora_1.default)("Loading data").start(); const [usersResponse, projectsResponse] = await Promise.all([ api.get("/api/users"), api.get("/api/projects") ]); spinner.succeed("Data loaded"); // Prepare user choices const users = usersResponse.data.map(user => ({ name: `${user.given_name || ""} ${user.surname || ""} (${user.email || "No email"})`.trim(), value: user.id })); // Group projects by company for better organization const projectsByCompany = {}; projectsResponse.data.forEach(project => { const companyName = project.company_name || "No Company"; if (!projectsByCompany[companyName]) { projectsByCompany[companyName] = []; } projectsByCompany[companyName].push(project); }); // Create a list of project choices with company headers const projectChoices = []; Object.entries(projectsByCompany).forEach(([companyName, projects]) => { // Add company header projectChoices.push({ name: `--- ${companyName} ---`, value: undefined, disabled: true }); // Add company's projects projects.forEach(project => { projectChoices.push({ name: ` ${project.name}`, value: project.id }); }); }); // Get user input const answers = await inquirer_1.default.prompt([ { type: "list", name: "userId", message: "Select a user:", choices: users, pageSize: 15 }, { type: "list", name: "projectId", message: "Select a project:", choices: projectChoices, pageSize: 20 }, { type: "datepicker", name: "date", message: "Select date:", format: ["Y", "-", "MM", "-", "DD"], default: new Date() }, { type: "number", name: "hours", message: "Hours worked:", default: 8, validate: (value) => { if (value <= 0 || value > 24) { return "Hours must be between 0 and 24"; } return true; } }, { type: "confirm", name: "confirm", message: "Create this time entry?", default: true } ]); if (!answers.confirm) { console.log(chalk_1.default.yellow("Time entry creation cancelled")); return; } // Format date as YYYY-MM-DD const formattedDate = luxon_1.DateTime.fromJSDate(answers.date).toISODate(); if (!formattedDate) { throw new Error("Invalid date format"); } // Display selected information console.log("\nCreating time entry with the following information:"); // Find selected user and project names for display const selectedUser = usersResponse.data.find(u => u.id === answers.userId); const selectedProject = projectsResponse.data.find(p => p.id === answers.projectId); console.log(`User: ${chalk_1.default.cyan(selectedUser ? `${selectedUser.given_name} ${selectedUser.surname}` : `ID: ${answers.userId}`)}`); console.log(`Project: ${chalk_1.default.cyan(selectedProject ? selectedProject.name : `ID: ${answers.projectId}`)}`); console.log(`Date: ${chalk_1.default.cyan(formatDate(formattedDate))}`); console.log(`Hours: ${chalk_1.default.cyan(answers.hours)}`); // Submit the time entry const submitSpinner = (0, ora_1.default)("Creating time entry...").start(); const timeEntry = { user_id: answers.userId, project_id: answers.projectId, date: formattedDate, hours_worked: answers.hours }; const response = await api.post("/api/time_entries", timeEntry); submitSpinner.succeed("Time entry created successfully"); // Display time entry details console.log(chalk_1.default.green("\nTime Entry Created:")); console.log(`ID: ${chalk_1.default.cyan(response.data.id)}`); console.log(`User: ${chalk_1.default.cyan(response.data.user_name || 'N/A')}`); console.log(`Project: ${chalk_1.default.cyan(response.data.project_name || 'N/A')}`); console.log(`Date: ${chalk_1.default.cyan(formatDate(formattedDate))}`); console.log(`Hours: ${chalk_1.default.cyan(answers.hours)}`); } catch (error) { console.error(chalk_1.default.red("Error creating time entry:"), error.response?.data?.error || error.message); if (options.verbose && error.response?.data) { console.error(chalk_1.default.gray(JSON.stringify(error.response.data, null, 2))); } process.exit(1); } } /** * Formats a date string as a readable format */ function formatDate(dateStr) { try { return luxon_1.DateTime.fromISO(dateStr).toLocaleString(luxon_1.DateTime.DATE_MED_WITH_WEEKDAY); } catch (error) { return dateStr; } }