diff --git a/index.js b/index.js index 3907d3b5..44b27aef 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,9 @@ -console.log("works!!", process.argv[2]); - const pg = require('pg'); +const timeStampUtil = require('./util/get-date.js'); + const configs = { - user: 'akira', + user: 'zachariah', host: '127.0.0.1', database: 'todo', port: 5432, @@ -11,26 +11,189 @@ const configs = { const client = new pg.Client(configs); -let queryDoneCallback = (err, result) => { - if (err) { - console.log("query error", err.message); - } else { - console.log("result", result.rows ); - } - client.end(); -}; +//Async/Await IIFE: --> connect --> query +(async () => { + try { -let clientConnectionCallback = (err) => { + await client.connect(() => { + console.log('connected'); + }); - if( err ){ - console.log( "error", err.message ); - } + //Query, takes callback to manipulate response when displaying data on CLI (see 'show' and 'showmeta' userArgs below) + const todoQuery = async (queryText, queryValues, cb) => { + try { + const res = await client.query(queryText, queryValues); + if (cb) cb(res); - let text = "INSERT INTO todo (name) VALUES ($1) RETURNING id"; + } catch (e) { + console.log('Error! ' + e.message); + } + } + // - const values = ["hello"]; + //CLI display for show / showmeta arguments + const listTitle = + ` + ╔═╗┌─┐┌─┐┬ ┬┌─┐ ╔╦╗┌─┐ ╔╦╗┌─┐ ╦ ┬┌─┐┌┬┐ + ╔═╝├─┤│ ├─┤└─┐ ║ │ │───║║│ │ ║ │└─┐ │ + ╚═╝┴ ┴└─┘┴ ┴└─┘ ╩ └─┘ ═╩╝└─┘ ╩═╝┴└─┘ ┴ + ` + // - client.query(text, values, queryDoneCallback); -}; + const userArgs = process.argv.slice(2); + + if (!userArgs[0]) { + + console.log(`Enter "add", "clear", "clearall", "crossoff", "show", "showmeta", "archive" or "unarchive" followed by appropriate values as arguments`); + + } else { + + console.log(userArgs); + + let queryT; + let queryV; + + switch (userArgs[0].toLowerCase()) { + + case 'add': + + if (userArgs[1]) { + + queryT = 'INSERT INTO to_do_items(time_stamp, item) VALUES ($1, $2) RETURNING *'; + + queryV = [timeStampUtil.getTimeStamp(), userArgs[1]]; + + todoQuery(queryT, queryV); + + } + break; + + case 'clear': + + queryT = `DELETE FROM to_do_items WHERE item = '${userArgs[1]}' RETURNING *`; + console.log(queryT); + + todoQuery(queryT); + + break; + + case 'clearall': + + queryT = 'DELETE FROM to_do_items RETURNING *'; + + todoQuery(queryT); + + break; + + case 'crossoff': + + queryT = `UPDATE to_do_items SET done = TRUE, updated_time_stamp ='${timeStampUtil.getTimeStamp()}' WHERE item = '${userArgs[1]}' RETURNING *`; + + todoQuery(queryT); + + break; + + case 'show': + + queryT = 'SELECT id, item, done, archived FROM to_do_items'; + + todoQuery(queryT, "", (res) => { + + console.log(`${listTitle}\n\n`); + + res.rows.forEach(obj => { + + let isItemDone; + + obj.done ? isItemDone = '[X]' : isItemDone = '[ ]'; + + if (!obj.archived) + console.log(`${res.rows.indexOf(obj) + 1}. ${isItemDone} - ${obj.item}`); + }) + }); + + break; + + case 'showmeta': + + queryT = 'SELECT * FROM to_do_items'; + + todoQuery(queryT, "", (res) => { + + console.log(`${listTitle}\n\n`); + + res.rows.forEach(obj => { + + let isItemDone; + let markedDoneInfo = ""; + + if (obj.done) { + isItemDone = '[X]'; + markedDoneInfo = `\nMarked done on ${obj["updated_time_stamp"]}`; + } else { + isItemDone = '[ ]'; + } + + if (!obj.archived) + console.log(`${res.rows.indexOf(obj) + 1}. ${isItemDone} - ${obj.item}\n Item added to list on ${obj["time_stamp"]}${markedDoneInfo}`); + }) + }); + + case 'archive': + + queryT = `UPDATE to_do_items SET archived = TRUE WHERE item = '${userArgs[1]}' RETURNING *`; + + todoQuery(queryT); + + break; + + case 'unarchive': + + queryT = `UPDATE to_do_items SET archived = FALSE WHERE item = '${userArgs[1]}' RETURNING *`; + + todoQuery(queryT); + + break; + + case 'stats-complete-time': + + queryT = `SELECT time_stamp, updated_time_stamp FROM to_do_items`; + + todoQuery(queryT, "", (res) => { + + //**To get average time completed based on crossoff timestamp and creation timestamp. To consider refactoring to simpler function as presently, am calling reduce twice. To consider storing timestamps in format more conducive for JS manipulation. + + let timeArray = [] + + const avgTotalMinutes = res.rows + .reduce((arr, obj) => { + + let timeDiff; + + if (obj["updated_time_stamp"]) { + timeDiff = Math.abs(new Date(obj["updated_time_stamp"].replace(/-/g, '/')) - new Date(obj["time_stamp"].replace(/-/g, '/'))); + + } + + if (timeDiff) arr.push(timeDiff); + return arr; + + }, timeArray) + + .reduce((sum, time) => { + return sum + time / timeArray.length / 60000; + }, 0) + + console.log('The average time taken to complete a task is ' + avgTotalMinutes.toFixed(2) + ' minutes'); + }); + + break; + + } + } + + } catch (e) { + console.log(e.message); + } -client.connect(clientConnectionCallback); +})(); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..5816b6bc --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "cli-todo-sql", + "version": "1.0.0", + "description": "![https://i.giphy.com/media/26ufnwz3wDUli7GU0/giphy.webp](https://i.giphy.com/media/26ufnwz3wDUli7GU0/giphy.webp)", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node index.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/zachariahchow/cli-todo-sql.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/zachariahchow/cli-todo-sql/issues" + }, + "homepage": "https://github.com/zachariahchow/cli-todo-sql#readme", + "devDependencies": { + "nodemon": "^2.0.3" + }, + "dependencies": { + "jsonfile": "^6.0.1", + "pg": "^8.0.2" + } +} \ No newline at end of file diff --git a/todo-table.sql b/todo-table.sql new file mode 100644 index 00000000..8956ddda --- /dev/null +++ b/todo-table.sql @@ -0,0 +1,10 @@ +/*psql -d todo -U zachariah -f todo-table.sql*/ + +CREATE TABLE IF NOT EXISTS to_do_items ( + id serial PRIMARY KEY, + time_stamp VARCHAR (30) NOT NULL, + updated_time_stamp VARCHAR (30), + item VARCHAR (50) NOT NULL, + done boolean, + archived boolean +); \ No newline at end of file diff --git a/util/get-date.js b/util/get-date.js new file mode 100644 index 00000000..00b8c8a3 --- /dev/null +++ b/util/get-date.js @@ -0,0 +1,7 @@ +module.exports.getTimeStamp = () => { + return new Date(Date.now() - new Date() + .getTimezoneOffset() * 60000) + .toISOString() + .slice(0, 19) + .replace('T', ' '); +}; \ No newline at end of file