Skip to content

Commit

Permalink
initial commit, some experimentation is left with webpack, but this w…
Browse files Browse the repository at this point in the history
…orks as of now"
  • Loading branch information
ashfame committed Jan 10, 2021
0 parents commit 1394e6f
Show file tree
Hide file tree
Showing 12 changed files with 17,505 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
public/build
5,228 changes: 5,228 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "focus",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"css": "postcss src/tailwind.css -o public/build/tailwind.css",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"autoprefixer": "^10.1.0",
"postcss-cli": "^8.3.1",
"tailwindcss": "^2.0.2",
"vue": "^2.6.12"
},
"devDependencies": {
"mini-css-extract-plugin": "^1.3.3",
"postcss": "^8.2.2",
"postcss-loader": "^4.1.0",
"webpack": "^5.12.2",
"webpack-cli": "^4.3.1"
}
}
6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
]
}
113 changes: 113 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<html>
<head>
<title>FOCUS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="/public/build/tailwind.css" />
</head>
<body>
<div id="app">
<div class="bg-gray-100 py-4 flex text-center">
<span v-for="(day,index) in days" :class="{ 'bg-gray-200': currentDay == index, 'text-gray-600': currentDay == index }" class="flex-auto inline-block uppercase p-2 mx-4 m-auto text-gray-400 rounded">{{ day }}</span>
</div>
<div class="sm:flex p-2">
<div class="flex-1 p-2">
<div class="p-2 pb-4">
<span class="block uppercase py-2 text-gray-500 bg-white border-8 border-gray-100 text-center rounded-t-lg">micro-saas</span>
<div class="bg-gray-100 p-4 text-center">
<div class="flex-row">
<span v-on:click="toggleHour(1)" :class="{ 'bg-red-400': hr[1] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(2)" :class="{ 'bg-red-400': hr[2] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(3)" :class="{ 'bg-red-400': hr[3] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(4)" :class="{ 'bg-red-400': hr[4] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(5)" :class="{ 'bg-red-400': hr[5] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
<div class="flex-row">
<span v-on:click="toggleHour(6)" :class="{ 'bg-red-400': hr[6] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(7)" :class="{ 'bg-red-400': hr[7] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(8)" :class="{ 'bg-red-400': hr[8] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(9)" :class="{ 'bg-red-400': hr[9] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(10)" :class="{ 'bg-red-400': hr[10] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
<div class="flex-row">
<span v-on:click="toggleHour(11)" :class="{ 'bg-red-400': hr[11] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(12)" :class="{ 'bg-red-400': hr[12] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(13)" :class="{ 'bg-red-400': hr[13] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(14)" :class="{ 'bg-red-400': hr[14] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(15)" :class="{ 'bg-red-400': hr[15] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
</div>
</div>
<div class="p-2">
<span class="block uppercase py-2 text-gray-500 bg-white border-8 border-gray-100 text-center rounded-t-lg">write blog</span>
<div class="bg-gray-100 p-4 text-center">
<div class="flex-row">
<span v-on:click="toggleHour(16)" :class="{ 'bg-red-400': hr[16] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(17)" :class="{ 'bg-red-400': hr[17] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(18)" :class="{ 'bg-red-400': hr[18] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(19)" :class="{ 'bg-red-400': hr[19] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(20)" :class="{ 'bg-red-400': hr[20] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
</div>
</div>
</div>
<div class="flex-1 p-2">
<div class="p-2 pb-4">
<span class="block uppercase py-2 text-gray-500 bg-white border-8 border-gray-100 text-center rounded-t-lg">consultancy</span>
<div class="bg-gray-100 p-4 text-center">
<div class="flex-row">
<span v-on:click="toggleHour(21)" :class="{ 'bg-red-400': hr[21] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(22)" :class="{ 'bg-red-400': hr[22] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(23)" :class="{ 'bg-red-400': hr[23] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(24)" :class="{ 'bg-red-400': hr[24] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(25)" :class="{ 'bg-red-400': hr[25] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
<div class="flex-row">
<span v-on:click="toggleHour(26)" :class="{ 'bg-red-400': hr[26] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(27)" :class="{ 'bg-red-400': hr[27] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(28)" :class="{ 'bg-red-400': hr[28] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(29)" :class="{ 'bg-red-400': hr[29] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(30)" :class="{ 'bg-red-400': hr[30] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
</div>
</div>
<div class="p-2">
<span class="block uppercase py-2 text-gray-500 bg-white border-8 border-gray-100 text-center rounded-t-lg">write books</span>
<div class="bg-gray-100 p-4 text-center">
<div class="flex-row">
<span v-on:click="toggleHour(31)" :class="{ 'bg-red-400': hr[31] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(32)" :class="{ 'bg-red-400': hr[32] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(33)" :class="{ 'bg-red-400': hr[33] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(34)" :class="{ 'bg-red-400': hr[34] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(35)" :class="{ 'bg-red-400': hr[35] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
<div class="flex-row">
<span v-on:click="toggleHour(36)" :class="{ 'bg-red-400': hr[36] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(37)" :class="{ 'bg-red-400': hr[37] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(38)" :class="{ 'bg-red-400': hr[38] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(39)" :class="{ 'bg-red-400': hr[39] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
<span v-on:click="toggleHour(40)" :class="{ 'bg-red-400': hr[40] }" class="inline-block bg-gray-300 p-4 hover:bg-red-400 cursor-pointer rounded"></span>
</div>
</div>
</div>
</div>
</div>
<div class="flex w-full bg-gray-100 p-4 pt-6">
<span class="flex-none text-gray-400" title="Just Do it!">
<svg class="mt-1 w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path></svg>
</span>
<div class="flex-auto text-center">
<span v-for="todo in todos" v-on:click="toggleTodo(todo.id)" :title="todo.content" :class="{ 'bg-yellow-200': todo.completed }" class="inline-block bg-gray-300 p-4 mr-1 hover:bg-yellow-200 cursor-pointer rounded"></span>
</div>
<div class="flex-none text-gray-400">
<a :href="bcAPIURL" target="_blank">
<svg class="mt-1 w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
</a>
</div>
</div>
</div>

<script src="/src/vue.js"></script>
<script src="/src/main.js"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FOCUS
=====

A simple Vue.js based Single Page Application (SPA) to manage my weekly focussed time (40hrs) divided into 4 main areas.

The idea is to not manage time, but make sure core focus areas get the attention you want on a weekly basis. The UI gives a progress of your weekly goal and helps you infer whether you are wasting time with not so important tasks (busy in productivity theatre) or doing the tasks that matter the most to you.

Anything outside of those items, are an overhead or errands, which shouldn't steal away your time, hence has lower visual priority as well.
I copy my Basecamp2's API JSON in localStorage for this to load, but you simply need a JSON in the following format:

```
[
{
"id": 1,
"content": "Launch rocket",
"completed": true
},
{
"id": 2,
"content": "Short Banks",
"completed": true
},
{
"id": 3,
"content": "Buy Bitcoin",
"completed": true
},
]
```

Currently I keep it open on one screen along side terminal while I work. I always want this in front of my eyes. You can set it as your Chrome's new tab view as well but you will have to run your local server for it.
92 changes: 92 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
var debug = true;

new Vue({
el: '#app',
data: {
days: [
'mon',
'tue',
'wed',
'thu',
'fri',
'sat',
'sun',
],
currentDay: 0,
weekStart: '',
weekEnd: '',
bcAPIURL: '',
hr : [],
todos: [],
year: 2021
},
beforeMount: function() {
this.figureOutDates();

this.bcAPIURL = 'https://basecamp.com/2626524/api/v1/projects/11781410/todos.json?due_since=' + this.weekStart;

// load basecamp todos
this.loadBasecampTodos();

// 40hrs focus hrs commitment
// see if we have info saved in localStorage first
var s = localStorage.getItem('savedHours');
try {
this.hr = JSON.parse(s);
} catch (error) {}

// and if not, then load default false values
if ( ! this.hr.length ) {
this.hr= [];
for (var i=1; i<=40; i++) {
this.hr.push(false);
}
}

// figure out dates on a loop, every hour so that upon a new day, it detects it soon enough
setTimeout(this.figureOutDates,1000*60*60)
},
methods: {
figureOutDates: function() {
var today = new Date();
this.currentDay = ( new Date().getDay() ) - 1; // match with index in days array
if ( this.currentDay == -1 ) {
this.currentDay = 6; // sunday
}
this.weekStart = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ( '0' + ( today.getDate() - this.currentDay ) ).slice(-2);
this.weekEnd = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ( '0' + ( today.getDate() - this.currentDay + 6 ) ).slice(-2);

if (debug) {
console.log( 'week start:',this.weekStart,' week end:', this.weekEnd );
}
},
loadBasecampTodos: function() {
var todos = JSON.parse( localStorage.getItem('todos') );
// remove todos that are beyond this week
for(var i=0; i<todos.length; i++) {
if ( true || todos[i].due_on <= this.weekEnd ) {
this.todos.push(todos[i]);
}
}
},
toggleHour: function(n) {
// n--;
// if (debug) {
// console.log('hour box clicked:', n + 1,'index: ', n)
// }
// let Vue be made aware of array update explicitly, so that UI can reflect
Vue.set(this.hr, n, ! this.hr[n]);
// save in localStorage
localStorage.setItem('savedHours',JSON.stringify(this.hr));
},
toggleTodo: function(id) {
for(var i=0;i<this.todos.length;i++){
if ( id == this.todos[i].id ) {
this.todos[i].completed = ! this.todos[i].completed;
}
}
// save in localStorage
localStorage.setItem('todos',JSON.stringify(this.todos));
}
}
});
3 changes: 3 additions & 0 deletions src/tailwind.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
Loading

0 comments on commit 1394e6f

Please sign in to comment.